2026/06/25

Google Play Console個人デベロッパーのテスター12人要件と対策

Google Playの個人開発者を阻む「テスター12人」の壁と向き合う

個人でコツコツ開発したAndroidアプリをいざリリースしようとしたとき、自分の前に立ちはだかったのがGoogle Play Consoleの「14日間連続で12人以上のテスターによるクローズドテスト」というルールだった(元々は20人だったが、2024年12月に12人へと緩和された)。2023年11月以降に作成された個人デベロッパーアカウントには、例外なくこの条件が適用される。友人や家族に頼むだけでは届きにくいこの数字に、自分も頭を抱えてしまった。この記事では、個人開発者がこのテスター要件をクリアするための現実的な解決策と、テストを進める中で自分が実際に詰まった落とし穴についてまとめている。

なぜ「12人・14日間」が必要なのか

Googleがこのルールを導入した背景には、アプリストア全体の品質向上と、スパム的な低品質アプリの排除があると言われている。企業アカウントにはこの制限はないが、個人用デベロッパーアカウントで新規アプリを作成する場合は、最初の本番リリースを行う前に必ずクローズドテストを経る必要がある。

この要件の厄介なところは、単に「12人のメールアドレスを登録する」だけでは終わらない点だ。登録されたテスター全員がアプリをオプトイン(テスト参加)し、さらに14日間連続で利用されていることがGoogle Playのダッシュボード上で確認されなければならない。もし途中でテスターがアプリを削除したり、全く起動しなくなったりすると、カウントが途切れて期間が延長される原因になる。

現実的なアプローチは「相互テスト」

身内だけで12人を集めるのは意外と大変だ。自分も最初は絶望したが、調べていくうちに同じ悩みを抱える開発者同士が助け合うコミュニティがいくつかあることがわかった。特に効果的だったのが、Discordの個人開発者向けサーバーやX(旧Twitter)での「相互テスト」の呼びかけだ。

Redditや日本の個人開発Discordコミュニティには、テスター募集専用のチャンネルが用意されている。そこで自分のアプリを紹介し、お互いにテスターになり合うのだ。この方法だと、相手も開発者なので「毎日テスト版アプリを立ち上げる」ことの重要性を理解してくれているため、テストの継続率が格段に高くなる。SNSで呼びかける際は、ハッシュタグ「#個人開発」や「#GooglePlayConsole」などを活用して、同じ状況にいる人を検索して直接コンタクトを取るのもいいだろう。

テスト開始までの具体的な設定手順

クローズドテストを始めるためのPlay Console側の設定手順を整理しておく。手順の不備で時間が無駄になるのを防ぎたい。

Googleグループの作成

テスターを個別にメールアドレスで追加することも可能だが、12人以上となると管理が面倒になる。Googleグループを作成し、そこにテスターのGoogleアカウントを登録してもらうのが一番スムーズだ。テスト参加者にはグループのリンクを共有し、各自で参加してもらう形をとる。

Play Consoleでのトラック作成

Google Play Consoleにログインし、対象 of アプリを選択後、左メニューの「テスト」>「クローズドテスト」へと進む。ここで新しくトラックを作成し、テスターの指定欄で先ほど作成したGoogleグループのメールアドレスを入力する。

# Googleグループを利用したテスター追加手順のイメージ
1. https://groups.google.com/ でグループを作成 (例: my-app-testers)
2. Play Console > クローズドテスト > テスターの追加 でグループのメールアドレスを入力
3. ユーザーにテスト用URL(オプトインURL)を共有してインストールを促す

テスト用アプリのビルド(AAB)をアップロードし、審査が通ったら「オプトインURL」が発行される。このURLをテスターに共有し、Web上で「テストプログラムに参加」ボタンを押してもらった後、Playストアからインストールしてもらう必要がある。URLを共有するだけではインストールできないため、手順書を事前に用意して共有すると親切だ。

自分が直面した「期間延長」のトラブルと対策

順調に進んでいるように見えたテストだが、10日目あたりで進行状況のインジケーターが止まってしまった。ダッシュボードを確認すると、テスト日数が正しくカウントされていない。「毎日利用」という基準の厳しさにここで直面したのだ。

Googleは明確な判定基準を公表していないが、どうやら「アプリがフォアグラウンドで起動され、一定のアクティビティがログとしてGoogle側に送信されること」が必要なようだ。ただインストールしたまま放置されている端末は、アクティブなテスターとしてカウントされない可能性が高い。

このトラブルを解決するために、自分は以下の対策を実施した。

  • プッシュ通知の実装: Firebase Cloud Messaging (FCM)を導入し、テスターに向けて1日1回「テストのご協力ありがとうございます。本日のアプリアクティビティをお願いします」といった通知を送信した。
  • ローカル通知でのリマインダー: プッシュ設定が面倒な場合は、アプリ起動時に翌日用のローカル通知をスケジュールする処理をコードに記述した。
  • 予備テスターの確保: 12人ぴったりでテストを回すと、1人でも離脱した瞬間に要件が未達になる。最初から15人〜20人程度をグループに招待し、少々の不稼働メンバーがいても基準を下回らないようにバッファを持たせた。

相互テスト時の個人情報とセキュリティ対策

ネット上の見ず知らずの人とテストを融通し合う場合、セキュリティと個人情報の扱いには細心の注意を払わなければならない。クローズドテストでは、オプトインしたユーザーのメールアドレスが一部開発者側に見えてしまう仕様があるためだ。

情報漏洩のリスクを減らすため、以下のトレードオフと対策を考慮するべきだ。

対策方法 メリット デメリット / トレードオフ
Googleグループの招待制利用 メールアドレスの直接公開を防げる グループの権限設定を誤るとメンバー一覧が見えてしまう
テスト専用エイリアスアドレスの推奨 プライベートのメールアドレスを保護できる テスター側で別アドレスを用意してもらう手間が発生する
メールアドレス登録制(個別リスト) 特定の相手のみに制限しやすい 手動での登録作業コストが高く、管理ミスが発生しやすい

自分はGoogleグループを利用したが、グループの設定で「メンバー一覧の閲覧」を管理者のみに制限することを徹底した。これを行わないと、参加したテスター同士でお互いのメールアドレスが見えてしまうトラブルに発展するため、初期設定時は確実にチェックを行っておく必要がある。

まとめ

2023年11月以降に作成された個人デベロッパーアカウントでの新規アプリ公開は、以前と比べて難易度が跳ね上がった。しかし、しっかりとした準備とコミュニティへの参加で、この壁は十分に突破できる。

  • テスター募集はDiscordやSNSでの「相互テスト」が現実的
  • 14日間のアクティブ利用を維持するため、通知によるリマインドを設計する
  • 離脱対策として15人〜20人程度の予備テスターを確保する
  • Googleグループの設定ではメンバー一覧の非公開化を徹底する

2026/06/23

スマホアプリ向けAPIでのHATEOAS設計は本当に悪手?実務的な妥協点と部分的採用のススメ

スマホアプリ向けAPIでのHATEOAS設計は本当に悪手?実務的な妥協点と部分的採用のススメ

スマホ向けAPIの設計をしていると、「URL変更によるアプリの強制アップデートをどう避けるか」とか、「期限付きトークンの管理をどうスマートに行うか」といった問題にぶつかる。この記事では、RESTの最上位原則とも言われるHATEOAS(Hypermedia as the Engine of Application State)をスマホアプリ向けAPIに適用する際の実務上のメリットやデメリット、そして完全採用で挫折しないための部分的採用という落としどころについて解説する。理想論に偏らず、クライアント開発者の実装コストやトラブル対処まで含めた現実的なAPI設計のヒントが得られると思う。

HATEOASって実際どうなんだろう?REST成熟度と実務のギャップ

HATEOASは、レスポンスの中に次に呼ぶべきAPIのリンク(URL)を埋め込んでおき、クライアントがそのリンクを動的に辿ることでアプリケーションの状態を遷移させる設計思想だ。よくREST APIの定義として引き合いに出される「Richardson Maturity Model(リチャードソン成熟度モデル)」では、最高レベルであるLevel 3に位置付けられている。

実務で使われるWeb APIのほとんどは、リソース単位のURL設計(Level 1)やHTTPメソッドの使い分け(Level 2)で止まっており、Level 3のHATEOASまでしっかりと実装している例は稀なんだよね。なぜなら、「クライアントとサーバーの結合度を極限まで下げる」という理想に対して、実装やメンテにかかるコストが明らかに高すぎると思われているからだ。特に仕様変更のスピードが速いスマホアプリの開発現場では、ドキュメントの更新が追いつかない中で動的なURLパースを入れるのは敬遠されがちだったりする。

ファイルDLフローにおけるHATEOASのレスポンス設計例

言葉だけで考えてもピンとこないため、具体的なユースケースを想定してレスポンス例を見てみよう。今回は「ファイル一覧取得 → 詳細取得 → ファイルダウンロード(DL) → ダウンロード完了確認(ACK)」という段階的なフローをHATEOASライクに表現してみた。

1. 一覧取得APIのレスポンス

まずはファイルの一覧を取得する。この段階で、各アイテムの詳細APIのURLや、ページネーションの次のページのURLを `_links` という標準的なキーの下に埋め込んで返す。

{
  "items": [
    {
      "id": "abc123",
      "name": "document.pdf",
      "size": 1048576
    }
  ],
  "_links": {
    "self": { "href": "/files" }, // 自分自身のエンドポイント
    "detail": { "href": "/files/abc123" }, // 詳細取得のための動的なリンク
    "next_page": { "href": "/files?page=2" } // クライアント側でクエリを組み立てさせないための次ページリンク
  }
}

2. 詳細取得APIのレスポンス

詳細APIを叩くと、ファイルのメタデータに加えて、一時的なダウンロードトークンを含んだ有効期限付きの署名付きURLが `download` リンクとして降ってくる。

{
  "id": "abc123",
  "name": "document.pdf",
  "version": "2.1.0",
  "checksum": "sha256:deadbeef...",
  "_links": {
    "self": { "href": "/files/abc123" },
    "download": { "href": "/files/abc123/download?token=xyz789&expires=1719100000" }, // 期限付きダウンロードURL
    "list": { "href": "/files" } // 一覧へ戻るためのリンク
  }
}

3. ファイルダウンロードAPI(バイナリ送信)

上記の `download` のリンク先へGETリクエストを送ると、ファイル本体がバイナリで返却される。しかし、バイナリデータ(`application/octet-stream`)のボディ部にはJSONリンクを含めることができない。そこで、レスポンスヘッダーを利用して次の完了確認(ACK)用のURLを受け渡す。

HTTP/1.1 200 OK
Content-Type: application/octet-stream
X-ACK-URL: /files/abc123/ack?token=xyz789&download_id=dl_001
Content-Length: 1048576

(バイナリデータ...)

4. ダウンロード完了確認(DL ACK)API

クライアントはヘッダーから抽出した `X-ACK-URL` に対し、ダウンロードが正常に終わったことを通知するPOSTを送る。完了後の遷移先リンクもレスポンスに含まれている。

POST /files/abc123/ack?token=xyz789&download_id=dl_001

{
  "status": "ok",
  "_links": {
    "detail": { "href": "/files/abc123" },
    "list": { "href": "/files" }
  }
}

設計思想の比較:なぜスマホ向けでは敬遠されるのか?

この設計のメリットは明らかで、クライアント側が「次に呼ぶべきAPIのパス」を一切知らなくていい点にある。サーバー側でエンドポイントの設計を変えたり、ダウンロード処理のドメインを別サーバー(CDNなど)へ逃がしたりしても、クライアントのコードを修正して強制アップデートをかける必要がない。また、状態管理がサーバー側で一元化されるため、「特定の状態のときだけダウンロードボタンを活性化する」といった制御が、リンクの有無だけで表現できる。

しかし、スマホアプリの開発でこれが敬遠されるのは、クライアント側の実装が複雑化するからだ。URLをソースコードに文字列定数として定義する(ハードコーディングする)方が圧倒的に直感的だし、多くのモバイル開発チームはその手法に慣れている。また、全レスポンスにリンク情報が乗り続けるため通信容量が微増することや、URLがクエリパラメータなどで動的に変化するためにHTTPキャッシュやローカルキャッシュのキー設計が非常に難しくなるというデメリットもある。

遭遇しがちなトラブルと解決策:OpenAPIスキーマとの相性問題

HATEOASを実務で導入しようとして自分が一番困ったのが、OpenAPI(Swagger)を使った静的なAPIスキーマ定義とクライアントコード自動生成(OpenAPI Generatorなど)との食い合わせの悪さだった。

OpenAPIは、基本的に「どこのURLにどんなスキーマのデータを送れば、何が返ってくるか」を静的に定義するツールだ。しかし、HATEOASのようにURLがレスポンスの値として動的に降ってくる設計だと、クライアント生成ツールが動的な `_links` のパース処理をうまく型定義できないという問題が起きる。特にSwiftやKotlinのコードジェネレータを使うと、レスポンスのオブジェクトがネストする中で循環参照が発生したり、ジェネリクスが解釈できずにコンパイルエラーを吐き出すエラーに直面することがある。

この根本原因は、生成されるモデル定義において、動的リンクを示す `href` のオブジェクトと静的なリソース定義を同じスキーマで表現しようとすることにある。このトラブルを解決するには、API仕様書(yaml/json)側で `_links` 部分を共通のコンポーネント(共通スキーマ)として定義し、かつクライアント側ではURLの解決だけを行う「リンクパーサー」をジェネレータの自動生成対象から除外して別クラスとして手動で定義し、疎結合に分離してパースするのが確実だ。以下のような定義ファイルを切り出しておくことで、コード生成時のエラーを綺麗に防ぐことができた。

# OpenAPI定義ファイルでの共通リンクターゲットの定義例
components:
  schemas:
    LinkObject:
      type: object
      properties:
        href:
          type: string
          format: uri
          description: "次に遷移するAPIの相対パスまたは絶対URL"
    ResourceLinks:
      type: object
      properties:
        self:
          $ref: '#/components/schemas/LinkObject'
        next:
          $ref: '#/components/schemas/LinkObject'

実務での落としどころ:部分的HATEOASの推奨

完全なHATEOASの実装は、学習コストやスキーマ定義のオーバーヘッドを考えると、多くの場合オーバーエンジニアリングになってしまう。だからこそ、実務では**「部分的HATEOAS」**を落としどころにするのがおすすめだと思う。

具体的には、静的なエンドポイント(例: `/files` や `/files/{id}`)はクライアント側で通常通りハードコードして扱い、今回のような「一時的なDLトークン付きURL」や「DL後の通知先(ACK URL)」などのように、状態や時間によって動的に生成しなければならないURLだけをレスポンスに含めるという設計だ。以下のように、リンク専用の `_links` という構造を持たせるのではなく、シンプルなフィールドとして返すのが最も破綻しにくい。

{
  "file_id": "abc123",
  "download_url": "https://cdn.example.com/files/abc123/download?token=xyz789&expires=1719100000",
  "ack_url": "/api/v1/files/abc123/ack?token=xyz789&download_id=dl_001",
  "expires_at": 1719100000
}

これならOpenAPIでの型定義も非常にシンプルで済むし、クライアント側も通常のJSONパースと同様のロジックで対応できる。動的に変わる重要なURL管理のメリットを享受しつつ、実装コストを最小限に抑えることができる実用的な折衷案だと思う。

まとめ

  • HATEOASはAPIレスポンスに次の遷移先URLを含める設計で、RESTの最高成熟度に相当する。
  • サーバー側でURLのルールや状態制御を一元化できるため、クライアントの変更耐性が上がるのが最大のメリット。
  • 一方で、クライアント側の実装負荷やOpenAPIなどのツールチェーンとの相性が悪いという実務上の大きな課題もある。
  • 解決策として、期限付きURLやACK通知先などの動的なパスにだけ絞ってレスポンスやヘッダーに含める「部分的HATEOAS」が実務の落としどころとして最適。

2026/06/17

: GoでLINEスタンプ制作を全自動化するCLIを作った話

白目まで透けて泣いた僕が、GoでLINEスタンプ制作を全自動化した話

LINEスタンプを作るとき、絵を描くのは楽しい。でもそのあとが地獄だった。背景を透過して、文字を入れて、サイズを揃えて、規定に合ってるか確認して、ZIPにまとめる。24枚+メイン+タブを手作業でやると、絵を描いた時間より加工の時間のほうが長くなる。耐えられなくなって、この単純作業を全部やってくれるCLIツールをGoで書いた。`stamp-tool` という名前にした。背景透過の「目が透ける問題」とか、文字のはみ出しとか、ハマりどころが多かったので記録しておく。

とりあえず4つのサブコマンドに分けた

最初から大きく作る気はなくて、自分の作業手順をそのままコマンドに割っただけ。フォルダを切る `init`、画像を加工する `process`、規定チェックの `validate`、申請用ZIPを吐く `zip`。普段やってる流れを写しただけだから迷わなかった。

stamp-tool init   myset      # フォルダと config.json を作る
stamp-tool process myset      # raw画像 → LINE仕様の透過PNGへ
stamp-tool validate myset     # 偶数サイズ・サイズ上限などを検査
stamp-tool zip      myset      # set_01.zip を書き出す

入力は画像生成AIで作った白背景のキャラ素材。これを `raw/` に置いて `process` を回すと、透過・文字入れ・サイズ調整まで終わった状態で `out/` に並ぶ。LINEの仕様を毎回手で確認しなくていいのが、思っていた以上に効いた。

「白を透明にする」だけだと目が消える

最初に書いた透過処理がひどかった。白いピクセルを片っ端から透明にしたら、キャラの白目も、白い服も、歯も、全部透けた。トーク画面で見ると目玉に穴が空いてて完全にホラー。LINEの審査でも背景の抜き残しや変な透過はリジェクト対象になるので、これは直さないとどうにもならなかった。

外側からBFSで「地続きの白」だけ抜く

解決のヒントは単純で、背景の白は必ず画像の端に接しているということ。逆に言うと、キャラの内側にある白は端と繋がっていない。だから画像の四隅・外周から探索を始めて、隣り合う白ピクセルだけを辿っていけば、背景だけを抜ける。いわゆるFlood Fillで、幅優先探索(BFS)で外周から内側へ「白の地続き」を広げていくイメージ。

しきい値はRGBがそれぞれ240/255以上なら白とみなす形にした。Goの `image` だと色は16bitで返ってくるので、240/255に当たる `61680` を境にしている。`visited` フラグで一度見たピクセルを管理して、キューで繋がりを辿るだけ。

// 外周をキューに積んで、地続きの白だけ透明化する
const threshold = 61680 // 240/255 を16bitにした値

for !queue.empty() {
    p := queue.pop()
    if visited[p] { continue }
    visited[p] = true
    r, g, b, _ := src.At(p.X, p.Y).RGBA()
    if r < threshold || g < threshold || b < threshold {
        continue // 白じゃない=キャラの輪郭。ここで止まる
    }
    dst.Set(p.X, p.Y, color.Transparent)
    queue.pushNeighbors(p) // 上下左右へ伝播
}

これでキャラの内側の白目は端と繋がっていないので残る。輪郭線で囲まれている絵柄なら、線がストッパーになってキレイに背景だけ抜ける。逆に輪郭が途切れてると白がキャラ内部までダダ漏れするので、素材側の線はちゃんと閉じておいたほうがいい、というのを身をもって学んだ。

長いセリフが枠からはみ出す

次に詰まったのが文字入れ。スタンプによってセリフの長さがバラバラで、「OK」みたいな短いやつはいいけど、「了解しました!」みたいに長いと横にはみ出る。LINEのスタンプ画像は最大で横370px・縦320pxと決まっているので、ここを超えるわけにいかない。

描画には `github.com/fogleman/gg` を使った。ありがたいことに、描く前に文字のピクセル幅を測れる。なので一回ダミーで測って、370pxに収まらなければフォントを縮める比率を計算して当てる、という形にした。

w, _ := dc.MeasureString(text)        // 描画前に幅を測る
if w > maxWidth {
    fontSize *= maxWidth / w           // はみ出したぶんだけ縮小
    dc.LoadFontFace(fontPath, fontSize)
}

さらに、文字が長いときはキャンバスの幅自体も広げるようにした。キャラの幅と文字の幅、大きいほうを基準にキャンバスを決める。ここで一個落とし穴があって、LINEのスタンプは自動で縮小される都合上、画像サイズが偶数じゃないとダメ。奇数で吐くと地味に弾かれる。なので最後に必ず偶数へ丸める処理を挟んでいる。

どんな背景でも読めるように縁取りを二重にした

LINEのトーク画面って、白背景の人もいればダークモードの人もいるし、パステルの壁紙にしてる人もいる。白文字だけだと明るい背景で消えるし、黒文字だけだと暗い背景で沈む。最終的に「白文字+黒の内フチ+黄色の外フチ」の二重縁取りに落ち着いた。これだと大抵の背景で文字が浮き上がる。

やってることは力技で、文字を少しずつ全方向にずらして描いて縁を作る。`gg` の `DrawStringAnchored` で、角度を変えながら16方向くらいに置いていく。先に外フチ(黄)を太めに、その上に内フチ(黒)、最後に本体(白)を重ねる順番が大事だった。フチ幅はフォントサイズに対する比率で出していて、内フチが約8%、外フチが約15%くらいにしている。

感情を足す漫画エフェクトの合成

焦りの汗とか、怒りマークとか、漫画的なエフェクトを乗せたくなる。これは `config.json` にエフェクト素材のどこを使うか座標とサイズで書いておいて、`image.Rectangle` と `SubImage` で必要なパーツだけ切り出して合成する形にした。キャラの大きさに合わせてアスペクト比を保ったまま拡縮して、右上あたりに置く。設定で位置を変えられるようにしたおかげで、同じ汗素材を使い回せて楽だった。

最後は機械にダメ出しさせる

人間の目視チェックが一番信用できないので、`validate` で機械的に弾くようにした。チェックしてるのはこのあたり。

項目規定
スタンプ画像の最大サイズ横370 × 縦320px 以内
画像サイズ偶数ピクセル
ファイルサイズ1枚あたり1MB以下
形式・透過PNG・背景透過

メイン画像は240×240、タブ(タグ)画像は96×74と別サイズなので、ここも `process` で一緒に生成して `validate` にかける。全部パスしたら `zip` が申請用のパッケージを吐いて終わり。検証で落ちた項目はログに出るので、何を直せばいいか一目でわかる。手作業で1枚ずつプロパティを見ていた頃と比べると、別世界だった。

まとめ

  • 背景透過は「白を全部消す」じゃなく、外周からのBFS(Flood Fill)で地続きの白だけ抜くと白目が守れる
  • 文字のはみ出しは `MeasureString` で事前測定→フォント縮小&キャンバス幅拡張で対応。サイズは必ず偶数に丸める
  • 二重縁取り(白+黒+黄)にすると、ダークモードでもパステル背景でも文字が読める
  • `validate` で最大370×320・偶数・1MB以下・透過を機械チェックしてからZIP化すると、審査前のミスが激減した

2026/06/09

YouTube・Twitchのチャットだけ表示するアプリを作った話

YouTube・Twitchのチャットだけ表示するアプリを作った話

ライブ配信を見るとき、映像とチャットを同じ画面で追わなくてもいい場面って、意外と多いんですよね。配信そのものはテレビやPCの大きい画面で流しておいて、手元のスマホではチャットだけを大きく読みたい。通信量やバッテリーを抑えたくて、映像は切ってコメントの流れだけ眺めていたいこともある。私自身がずっとそういう見方をしていて、その不便さを消すために作ったのが ChatTube という Android アプリです。YouTube と Twitch のライブチャットだけを表示する、それ以外は何もしないアプリで、この記事では何ができて、どう使うのかをまとめておきます。

映像はいらない、チャットだけ読みたいという需要

YouTube や Twitch の公式アプリは、当然ながら映像とチャットがセットで表示される。よくできているけれど、「チャットだけを軽く見たい」という用途には少しオーバースペックなんだよね。映像のデコードが走るぶん端末は熱くなるし、ギガも減る。セカンドスクリーンとしてスマホを置いて、コメントだけを流し読みしたいときには、もっと身軽なものがほしくなる。

ChatTube は、その「チャットだけ」を切り出したアプリです。配信映像は一切表示せず、YouTube と Twitch のライブチャット欄だけを出す。映像を持たないぶん動作が軽くて、コメントの流れに集中できます。

使い方は「URLを貼る」だけ

チャットを開く手順はシンプルです。画面上部の「+」からブックマークを追加して、見たい配信の動画URL、またはチャンネルのURLを貼り付ける。あとは一覧から項目をタップすれば、そのチャットが開きます。

もっと楽なのは共有経由で、YouTube や Twitch のアプリ側で配信ページを開いて「共有」メニューから ChatTube を選ぶと、URLをコピーして貼り直す手間なく登録できます。一度登録した配信はブックマーク一覧に残るので、よく見る配信者を並べておけば次からはタップ一発でたどり着けます。

YouTubeの「配信ごとにURLが変わる問題」を解決する

YouTube を追っている人なら一度は困ったことがあると思うんだけど、YouTube のライブ配信は配信のたびに動画URLが変わる。昨日ブックマークしたURLは、今日の配信ではもう別物になっている。これが地味に面倒で、結局その都度チャンネルを開いて「いま配信中の枠」を探すことになるんですよね。

ChatTube では、動画URLの代わりにチャンネルのURLを登録できます。たとえばこういう形式です。

https://www.youtube.com/@チャンネル名

チャンネルURLを登録すると、一覧にその項目が「チャンネル」バッジ付きで表示される。タップした時点でそのチャンネルがライブ配信中なら、いま流れている配信のチャットを自動で開いてくれます。配信していなければ「配信していません」と通知するだけで、画面は切り替わらない。配信ごとにURLを探し直す必要がなくなるので、毎回同じ配信者を追っている人ほど恩恵が大きい機能だと思う。

配信中かどうかが一覧でわかる

ブックマーク一覧では、各項目の配信状態がアイコンで出ます。🔴 が配信中、⚫ が配信なし。一覧を開いた瞬間に「いま誰がやっているか」がひと目でわかるので、一つずつ開いて確認する手間がない。状態は一覧右上の更新ボタンで取り直せるから、配信が始まったタイミングで押せば最新の状況に追いつけます。

コメントの投稿にも対応

ChatTube は読むだけのアプリではありません。チャットにコメントを書き込むこともできます。投稿にはログインが必要で、画面上部のログインアイコンから YouTube(Googleアカウント)または Twitch にログインする。ログアウトは設定画面からいつでもできます。映像なしの軽い画面のまま、配信に参加できるわけです。

チャットを広く・見やすくするための工夫

チャットだけを表示するアプリなので、その表示領域をどれだけ快適にできるかにはこだわった。チャット表示中は数秒でヘッダーが自動的に隠れて、画面いっぱいにコメントが広がります。もう一度出したいときは画面の上端をタップするだけ。この「没入モード」は設定の「ヘッダー自動非表示」でオン・オフを切り替えられます。

設定画面では、ほかにもテーマ(ライト/ダーク)、表示言語、フォントサイズ、チャットの余白、画面の常時オンを変更できます。チャットの余白はピクチャーインピクチャー(PiP)の小窓表示に合わせるための調整で、映像を別アプリの小窓で流しながら ChatTube でチャットを読む、という使い方にも寄せられる。配信を流しっぱなしで眺めたいときは、画面常時オンにしておくと画面が消えずに済みます。

まとめ

  • ChatTube は映像を表示せず、YouTube・Twitch のチャットだけを軽く読める Android アプリ
  • チャンネルURLを登録すれば「いま配信中の枠」のチャットへ自動で飛べて、YouTubeのURL変化問題を回避できる
  • Google または Twitch にログインすればコメント投稿もできる
  • 没入モードや余白・フォント調整で、チャットを広く見やすく保てる

「映像はいらない、チャットだけ」という人にはちょうどいいはずです。ChatTube は Google Play で公開しているので、気になった人はこちらからどうぞ。

2026/06/05

Webサイトのモックアップ作成はAIにHTMLを書かせるのが速い

Webサイトのモックアップ、もうAIにHTMLを書かせればいいんじゃないか

結論から言うと、Webサイトのモックアップ作成はAIにHTMLを直接書かせるのが一番速い。自分はここ半年くらい、デザインツールでワイヤーフレームを引く工程をほぼやめて、ClaudeやChatGPTに「こういうサイトのモックをHTML 1ファイルで」と頼む方式に切り替えた。実際に使っているプロンプトとハマりどころを、自分の経験ベースで書いていく。

なぜデザインツールではなくHTMLモックなのか

以前はFigmaでモックを作っていた。ただ、自分のような開発寄りの人間にとって、Figmaは正直オーバースペックなんだよね。オートレイアウトの設定に時間を食って、肝心の「どんなサイトにするか」を考える時間が削られていく感覚があった。

HTMLモックには明確な利点がある。ブラウザでそのまま開けるから、クライアントや社内メンバーに「このURLを開いて」で共有が終わる。ウィンドウ幅を縮めればレスポンシブの挙動も実物で確認できる。静止画のモックだと「スマホだとどう見えるんですか」という質問に毎回別画面を用意する必要があったけど、HTMLならその場で縮めて見せるだけ。

そして何より、HTMLを書く作業自体をAIに丸投げできるようになったのが大きい。手書きでHTMLモックを作るのは正直つらいけど、書くのがAIなら話は別だと思う。体感だけど、以前Figmaで半日かけていたレベルの提案用モックが、いまはプロンプトを書いて修正指示を数回出すだけ、30分前後で形になっている。

実際のやり方

基本は「1ファイル完結」で頼む

自分がいつも使っているプロンプトの型はこんな感じ。

以下の要件でWebサイトのモックアップを作って。
- HTML 1ファイル完結(CSSは<style>タグ内に書く)
- 構成: ヘッダー / ヒーロー / 特徴3つ / 料金表 / お問い合わせフォーム / フッター
- ターゲット: 中小企業の経営者
- 配色: 紺をベースに、アクセントは1色だけ
- ダミー画像は使わず、CSSのグラデーションか単色で代用
- 文言は「ここに入ります」ではなく、それらしい日本語を入れる

ポイントは外部依存をなくすこと。CSSを別ファイルにされたり、CDNから画像を引っ張られたりすると、ファイルを渡した相手の環境で崩れることがある。「1ファイル完結」と明示しておけば、メールに添付するだけで誰でも開ける成果物になる。

文言はダミーにしない

地味に効くのが「それらしい日本語を入れて」という指示。モックの段階で「サンプルテキストサンプルテキスト」が並んでいると、見る側はデザインじゃなくて空白の文言が気になってしまう。文言まわりは、業種とターゲットを添えるとぐっと良くなる。

・文言はダミー禁止。税理士事務所のサイトという前提で、
  40〜50代の個人事業主に響くキャッチコピーと説明文を入れて
・キャッチコピーは20字以内、説明文は各80字程度

AIならそれらしいキャッチコピーや説明文を一緒に生成してくれるので、モックの完成度が一段上がる。実際、クライアントに見せたとき「この文言ほぼこのままでいいね」と言われて、コピーライティングの工数まで浮いたことがあった。逆にここをダミーのままにしておくと、打ち合わせの場で文言の話に脱線して、肝心のレイアウトの議論が進まなかったりする。

修正は会話で回す

初回の出力が微妙でも問題ない。修正指示を会話で投げれば、数十秒で修正版が返ってくる。自分が実際によく使う修正プロンプトはこのあたり。

・ヒーローセクションの高さを画面の70%にして、キャッチコピーをもっと大きく
・料金表は3プラン横並び。真ん中のプランを「おすすめ」として少し目立たせて
・全体的に余白が窮屈。セクション間の余白を1.5倍くらいに
・スマホ表示のとき、特徴3つは縦積みにして

Figmaで自分で直すより圧倒的に速い。自分の場合、初回生成から3〜5往復くらいで「見せられるモック」に到達することが多い。

ハマったポイントと対策

いいことばかり書いてきたけど、ハマりどころもある。

まず、AIが作るデザインは放っておくと似たり寄ったりになる。紫系のグラデーション、カード型レイアウト、絵文字アイコン。いかにも「AIが作りました」という見た目になりがちなんだよね。対策としては、配色とトーンを具体的に指定すること。自分はこういう指示を最初のプロンプトに足している。

・配色は #1e3a5f(紺)をベースに、アクセントはオレンジ1色だけ。グラデーション禁止
・絵文字アイコンは使わない
・無印良品の公式サイトみたいな、余白多めで色数を絞った落ち着いたトーン
・フォントは游ゴシック系。丸ゴシックは使わない

「参考サイトの雰囲気を文章で説明する」のが特に効く。デザインの専門用語を知らなくても、「〜みたいな感じ」で伝えるだけでだいぶ変わる。

もうひとつは、モックのHTMLをそのまま本番に流用したくなる誘惑。これはやめたほうがいい。モック用に生成されたコードはアクセシビリティやセマンティクスが甘いことが多くて、本番品質にするには結局書き直しに近い手間がかかる。自分は「モックは使い捨て、本番は別物」と割り切ることにしている。

ツールの選択肢としては、ChatGPTやClaudeのようなチャット型のほか、Vercelのv0みたいなUI生成特化のサービスもある。ただ個人的には、日本語の文言込みで作るなら普通のチャット型AIで十分というのが体感。プレビュー機能つきのチャットAIなら、生成結果をその場で確認しながら会話で直せる。

デザインツールとの使い分け

じゃあFigmaが要らなくなったかというと、そうでもない。デザイナーが入るプロジェクトでは、コンポーネント管理やコメント機能を含めてFigmaのほうが回しやすい。自分の整理はこう。

  • 提案段階の叩き台、個人開発、社内ツール → AIにHTMLモックを書かせる
  • デザイナーと共同作業する本格的な案件 → Figma
  • 「とりあえず見た目のイメージを共有したい」だけ → AIのHTMLモックで十分

体感だと、自分の仕事の8割は上の1番目と3番目で済んでいる。叩き台の段階で時間をかけても、どうせ要件が変わって作り直しになる。だったら30分で出せるHTMLモックを使い捨てる前提で回したほうが、トータルでは速い。モックに対する心理的なコストが下がると、「とりあえず2案作って並べて見せる」みたいな贅沢な使い方もできるようになるしね。

まとめ

  • モックアップはAIにHTML 1ファイルで書かせるのが速い。ブラウザで開けてレスポンシブ確認もできる
  • プロンプトは「1ファイル完結・構成・配色・それらしい日本語の文言」を指定する
  • AIっぽい見た目を避けるには配色とトーンの具体指定が効く
  • モックのコードは使い捨て。本番流用はしない