980円の有料記事を買って、後悔したことがあります。開いてみたら、冒頭を薄く引き伸ばしただけだった。
買う前に何が書いてあるかだけは見える設計にしたい。この一点が、Lovaiのブロック単位課金の出発点です。
Lovaiでは、投稿のブロックごとに無料・有料・非公開を設定できます。同じ投稿の中に、誰でも見ていいデータと、買った人しか見ちゃいけないデータが混在する。
この保護の設計で、AIとの壁打ちが一番濃くなりました。
自分はコードが書けません。3つ目のサービスなのでAIとの進め方にはだいぶ慣れていましたが、それでも最初にAIが出してきた設計は、そのまま採用できるものではなかった。
有料ブロックの存在ごと見えなくなる設計だったんです。
技術的には正しい。「見せない」という要件は完全に満たしている。でもプロダクトとしては致命的でした。
存在が見えなければ、購入判断ができません。読者は「ここに有料の情報がある」ということすら知らないまま、ページを離れる。買う理由が生まれない。
ここで分かったのは、AIは「守る」は得意でも、「売れる見せ方」の前提を勝手に補ってはくれないということでした。「何を守るか」ではなく「何を見せるか」を決めるのは、ユーザーの購買心理を知っている人間の仕事だったんです。
AIに「存在は見せて、中身だけ隠して」とフィードバックしたら、即座にテーブル分離の設計が返ってきました。
post_blocksにメタデータ(タイトル・概要・ブロックの種類)を持たせて、post_block_contentsに本文を分離する。
差分はこうです。
- 却下案:premiumブロックの行ごと返さない
- 採用案:行は返す、contentだけnullにする
この1行の違いが、「有料ブロックの存在が見えるかどうか」を決めます。
これをSupabase RLS + Security Definer関数でDB層に組み込みました。クライアント側のフィルタでは突破できない構造です。
読者にはタイトル・概要・ブロック種別が常に見えていて、premiumブロックの本文だけがnullで返る。「ここに有料の情報がある。何についてかはわかる。中身だけ見えない」という状態です。その周辺の無料ブロックも読めるから、有料部分の価値を推測できる。
「全部見せるか、全部隠すか」の二択じゃなくて、段階的に判断材料を出す設計です。
もう一つ、かなり危なかった場面があります。
購入レコード(誰がどの投稿を買ったかの記録)の保護で、AIは「作成だけ禁止すれば安全です」と提案してきました。
一見正しそうですが、穴がありました。
購入フローは「仮登録→決済→完了」で動きます。Stripeの決済完了Webhookを受けてから、仮登録のレコードを「完了」に更新する。作成を禁止しても、更新が開いていたら、仮登録のレコードを「完了」に書き換えられてしまう。お金を払わずに有料コンテンツが見れる状態です。
「本当にこれで安全?決済フロー全体で見たとき、ユーザーが触れる部分は全部塞がってる?」と聞き直して、初めて発覚しました。
結局、購入レコードはユーザーからの作成・更新・削除を全部禁止。書き込みはサーバー側のWebhookハンドラだけが行う設計に変えました。
課金まわりは「作成・更新・削除のどれか一つでもユーザーが触れたらアウト」くらいの感覚で見るのがいいかもしれません。
AIは守る設計を出してくれます。でも、何を見せて何を隠すか、どこに更新穴が残るかまでは、人間が疑わないとそのまま通ります。
「有料ブロックの存在を隠すな」は購買心理の判断でした。「購入レコードの更新を塞げ」は決済フローをユーザーの動線として追った結果でした。どちらもコードの話に見えて、実際はプロダクトの思想の話です。
AIの最初の案は、技術的に正しいことが多い。だからこそ、そのまま通しやすい。でも「技術的に正しい」と「プロダクトとして正しい」は別の話で、その差分を疑うのは作り手の仕事だと思っています。
---------------------
Lovaiのプロダクトページを見てもらえれば、今の形がわかります。
https://www.solomaker.dev/products/3c17d597-39e3-4222-9147-caede748153d
AIとの設計判断の進め方や、ブロック単位の権限設計に興味があれば、ディスカッションで聞いてください。
Lovai公式サイト
https://lovai.app/
コメントはまだありません
読み込み中...