"この現象に名前をつけたい!" という気持ちを満たせる大喜利サービス「Donzuba」を個人開発しました
Donzuba(ドンズバ)という大喜利サービスを個人開発しました。
Next.js(App Router)と Supabase を使って開発しています。
この記事では、技術的なお話もしていくので最後までご覧ください!
Donzubaは何をするWebサービスなのか?
世の中には誰しもが経験したことがあるのに名前すらない謎の現象が溢れています。
- トイレに入った途端、急に宅配便が届いてしまう謎の現象。
- 洗い物とかトイレするの想像しちゃってハンドクリーム塗るタイミングが分からない。
- 数時間考えても解決しなかったのに一旦寝て起きたら30秒で解決しちゃう現象。
- めちゃくちゃ空いてたのに自分がお店に入って数秒でかなり混雑してくる現象。
みんな経験したことあるのに現象名が付いてないのおかしくないですか?
待ってるだけでは永遠に名前つかなさそうなので、経験した謎現象(あるある)を投稿して、みんなで "ドンズバ" な名前考えちゃおう!というサービスです。
※ なお、"ドンズバ" という言葉は死語の模様......。
テクノロジー業界特有の現象にも名前つけていきませんか!!!
Donzubaの開発を始めた背景(調査)
みなさんは X(Twitter)で「この現象に名前をつけたい!」という投稿を見たことはありませんか?
Yahoo!リアルタイム検索「現象 名前」の検索結果で、月間13,260件も投稿されている定番ポストになっています。 (参考:30日間のポスト数の推移)
半分以上がネタ投稿なので、これを需要と呼ぶのは乱暴ではありますが、一応あっても面白いのかなと思い開発を開始しました。回答が付かなくても "あるある一覧" が見れるだけでも面白いなぁと思った次第。
技術構成
- Next.js(App Router)
- Supabase(DB + バックエンド)
- Cloud Run(Next.jsのホスティング)
Google Cloud Storage(プロフ画像のストレージ)- Netlify(動的OGP生成、署名付きURLの発行)
このような技術構成で作りました。
Next.js(App Router)
Donzuba開発において注意した点を挙げておきます。
- ユーザー生成コンテンツ部分はCSRするようにしています。認証についても同様に全てブラウザ側で行っています。【サーバー側の処理を減らすため】
- スケルトンスクリーンを導入した。
- いいね!ボタンが連打されても過剰にリクエストが飛ばないように対策した。
- モバイルファーストでかなり怠惰なUI実装をした。(単に手抜きではなくてモバイルユーザーのことだけを考えて作った。PCユーザーは2割ぐらいですし...。モバイルぞっこん開発)
上記の中から、「かなり怠惰なUI実装」について説明します。
こんな経験はありませんか?
「文字数増えたらレイアウト崩れそうだなぁ...。横幅375pxだといいけど360pxサイズでアクセスされたら崩れちゃうなぁ...」
...
.........
..................だるすぎ!!!
でも、もうそんな心配は捨ててください。
この問題を一瞬で解決しちゃう方法過去に記事化したので下記をご覧ください。
簡単に説明すると、デザインデータを横幅360pxで用意し、body,html の font-size: 2.778vw;
とすることで、 1rem ≠ 10px
として実装しています。つまり、 w-[4rem]
なら横幅360pxのときに width: 40px相当、 h-[6.4rem]
なら64px相当になります。
【▲挙動】まるで一枚画像のように全てが可変で動いてくれるようになります。
これの利点は横幅360px以上の全てのスマホでほぼ同じ見た目にできるので、細かい修正がほとんど発生しないという点です。また、嬉しい副作用としてスケルトンスクリーンの実装がかなりやりやすかったです。(Chromeのシミュレーターの幅を360pxにしておけば、viewboxやxやyの値をブラウザの値を見たままスケルトンスクリーンに落とし込めばいいだけ!)
▼ こんなにピッタリ!(実際のブラウザ上での動きをキャプチャした)
テキストは10pxより小さくならない点は注意する必要があります。
PCユーザーの利用が見込めないWebアプリケーションであればこの手法を取り入れてモバイル開発に集中してしまってもいいんじゃないかと思っています。(PC表示時に左右の空きが気になるのであれば、左右にメニューを設置してそこからコンテンツエリアを操作するような補助的な項目を表示すると良いかもしれませんね。)
PCでもそれなりに見えるようにする調整(fixed要素を調整したり、背景を追加したり)は1時間弱で終わりました。
レスポンシブなのに決め打ちの値で実装できる楽さは圧倒的です!
Supabase
ここ2年間で急速に人気が出てきているBaaSです。
オープンソースで開発されているのでセルフホスティングも可能になっています。Supabase社が滅んでしまっても最悪どうにかなるのが嬉しいですね。(滅びないで!!)
他にもSupabaseの素晴らしい点は開発のしやすさと安心感にもあります。
- 無料枠がすごく広い。
- CRUDがとても簡単。
- CHECK制約やRLSを正しく設定していればエラー周りの処理を勝手にやってくれて楽ちん。
- TypeScriptの型生成ができるCLIコマンドがある(supabase gen types typescript)
- X(Twitter)などのプロバイダー認証が簡単に実装できる。
- PHPなどの仲介役が不要で、DBと直接通信している気分で開発できる。
- Postgresのトリガー機能が便利すぎる。(hogeテーブルにINSERTやDELETEなどが入ったら任意の関数を勝手に実行してくれる。トリガーbeforeを使って値を検証することもできる。)
- Supabaseの中の人に日本語ネイティブな タイラーさん(@dshukertjrjp)がいるので、何かあったときに聞けるかもしれないという安心感。
▼ SupabaseでTwitter認証をする手順
便利なSupabaseですが、注意しなければならない点もあります。
▼ 暴力的なスクレイピングの餌食になりやすいと感じています。(たった1リクエストで大量にデータを持っていかれちゃう恐れ。)そこで、SELECTだけは .rpc()
経由で実行すべきという考えに至りました。(クローズドな管理画面であればブラウザから直接SELECTを実行しても良い。)
▼ フロントエンドでDB操作する際に注意すべきことの自分なりのルール
また、認証パッケージとしては本来は @supabase/ssr
を使うべきですが、Twitterユーザー名に @ や -
が入っていると認証失敗してしまう不具合を発見したため、@supabase/auth-helpers-nextjs
を使っています。問題修正されればすぐに乗り換えます。
Supabaseは便利ですし、かなり将来性にも期待しているのですが、細々とした不具合に悩まされる部分はちょっと辛いですね。僕はそれを乗り越えてでも使いたくなる魅力をSupabaseに感じています。
Cloud Run
Donzuba本体のデプロイ先です。
使った分だけ支払うという料金形態が嬉しいですね。
VercelがCloud RunにデプロイするためのDockerfileを用意してくれています。かなり簡単にデプロイできます!
Google Cloud Storage(間に合わず:未実装)
ユーザーのプロフィール画像はこちらに格納しています。(任意で変更した場合だけ。Twitter認証して画像変更してない場合はTwitterのストレージサーバーから直接取得しています。)
Supabase Storageを使わなかったのは課金までのハードルを高くするためです。Supabaseは帯域幅の制限が厳しく、画像を配信しちゃうとすぐに課金が必要になりそうだと思ったので、画像だけ安価なCloud Storageに逃がすことにしました。
ちなみに Cloudflare R2も検討しましたが、利用サービスをあれもこれも増やすと混乱するのでやめておきました。(画像少ないですし!)
Netlify
本体のCloud Runとは別にNetlifyも利用しています。動的OGP画像の生成サーバーやGoogle Cloud Storageの署名付きURLの発行サーバーとして使っています。
Netlifyには全く別の Next.js を入れていて、そこで @vercel/og を使って動的OGP画像の生成をしています。(LINE Seedというフォントを使わせて頂きました。)
わざわざNetlifyを使った理由は下記の通り。
- 動的OGP画像を無料で作りたい。
- Cloud Runの計算コストを節約したい。
- Supabaseの帯域幅をとにかく節約したい。
ということで、月100GBのデータ転送量が無料かつ、Next.jsのホスティング可能なNetlifyを採用しました。Netlifyは自動的にキャッシュを取ってくれるので、連続してリクエストされても比較的に安心です。(ビルド時間には注意しましょう。)
ちなみに、動的OGP画像生成を無料で実現するまで紆余曲折ありました。
- Deno DeployにデプロイしたしたもののImageResponseの出力ができなかった。
- Netlify Edge Functionsにデプロイしたがタイムアウトが連続してしまい使い物にならなかった。
- Netlify Functionsも試したがImage Responseに対応してなかった。
ということで、かなり時間を溶かしてしまいました...。
かかった費用
- Cloud Run -> 無料クレジット分があるので0円
- Netlify -> 0円
- Supabase -> 0円
- ドメイン代 -> Xserverドメインで取得。A8経由でセルフバック100%なので実質0円
合計0円!!!
困ったときに相談に乗ってくれたAIさん
どちらも0円で丁寧な回答をしてくれて最高です!
Donzuba開発で心がけたこと
- サービス名をしっかり考えた。既存の言葉でピッタリなやつ探した。自慰的造語は覚えるのカロリー使うので。(死語だけど)
- モバイル利用だけに集中したことやSNS流入だけを意識した作りにした。
- サーバーの仲介を減らすように意識した。(自分らのデータは自分らのデバイスで計算しろ!)
- 無限スクロール箇所では、ページバック時にスクロール位置がちゃんと戻るようにした。
- 「お題」と「回答」それぞれがメインコンテンツなので色分けをした。
- サービスの特性上、文字だけのコンテンツなので、注目すべきコンテンツ文字がひと目でどれなのかが分かるように周辺の色味を抑えた。
- メール送信系の料金がかかるの嫌なので登録はTwitter認証だけに絞った。(言葉遊び好きな人はだいたいTwitterやってるはずだし。)
- 「回答」は文字数が少ないほど大きく表示されるようにした。(use-fit-textは神)
- @hoge が重複したときに自動の文字列に置き換える。Twitter認証のみだし、Twitter側のスクリーンネームは頻繁に変更しないはずなので、基本的に重複は発生しないが、万が一に備えておきたい。緊急性は薄いので後回しにした。
今後の課題感
- 回遊の仕組みが全くない。(検索や類似コンテンツの表示とか。)
- 並び替え機能
- ユーザーページの投稿一覧が常に最新な状態であるべき(現状はキャッシュ効きすぎて投稿できたかどうかの確認ができない。useSWRInfiniteの使い方難しい...。)
- 「回答」のベストアンサー機能を付けるか否か。(面白そうな表現を誰かが気に入って使い始めて、自然と拡がるのが言葉なので、確定を押し付けるのも疑問が残る。Donzubaはあくまでネタ帳ぐらいの立ち位置でありたい。)
ご支援をお願いします!
技術的なお話は以上です。最後にお願いがあります。
下記をリポスト(リツイート)で応援して頂けると嬉しいです!
何か質問があればTwitterまたはZennのコメントにてお気軽にどうぞ!
A【3,000円支援できる】0円でできる支援【DMMプレミアム(VOD)】
30日間無料のDMMプレミアムというVODに登録してください。
新規登録で3,000円が僕に入ります!0円で3,000円湧いてしまう最強のバグです!
普通に映画とかコンテンツを楽しんで30日以内に解約すれば0円です。解約は手動でやる必要があるのでご注意ください。
B【1,000円支援できる】90%OFFで電子書籍を購入して支援【DMMブックス】
もしくは、技術書やビジネス書などの電子書籍を購入するという方法もあります。90%OFFクーポンを使いながら電子書籍を購入すると、新規購入者であれば、僕に1,000円入ります!
例えば、
2,000円の商品なら200円の支払い。
1500円の商品なら150円の支払い。
こんな感じで 数百円で1,000円も支援できてしまう謎の錬金術 です!
みなさまのご厚意は個人開発で活用させて頂きます。
Donzubaを応援よろしくお願いします!
明日の 個人開発 Advent Calendar 2023 は @minomusi_studyさんです。
Discussion