『エンジニア・プログラマにしか使えないSNSを作ってみた話』のクライアントを作ってみた話
何を作ったか
2021年7月にQiitaに投稿された『エンジニア・プログラマにしか使えないSNSを作ってみた話』という記事で紹介されているSNSのウェブクライアントを、7月の4連休を使って作ってみました。
『エンジニア・プログラマにしか使えないSNS』とは
本当のエンジニア・プログラマしか使えないSNSを作ってみました!
つまり、WebApi提供のみのSNSです
一般ピープルが使うようなフロントエンドなんてありません!!
Postmanなり、なんなりを使って叩いてください
要はバックエンドだけ、APIだけのSNSです。
僕は普段から公開APIを使って好きなようにフロントエンドだけを作るのが好きなので、この記事を読んだときにビビッときて、時間ができたらこのSNSのクライアントを作ってみたいと思っていました。
技術スタック
- TypeScript
- Next.js
- SWR
- Tailwind CSS
- Vercel
上記のような構成で作りました。この構成は結構お気に入りで、最近何かを作り始めるときは毎回この構成で作っています。
コードはGithubで公開しているので、興味があればぜひ見てみてください。
開発について
API自体がTwitter風のSNSアプリケーションなので、基本的にはそれにフィットするようにUIを考えて作っています。その上で、以下のようにこだわったみた点やAPIの仕様上気にしなければならなかった点がありました。
IPアドレスからユーザーIDが作られる
なんといってもここが一番苦労した点です。
最初は特に意識してなかったのですが、テキストを投稿したりユーザー情報を登録する機能を作り始めた際に、自分のユーザーIDを取得する方法がわからずつまづきました。
サービスの特性上、テキストを投稿しているのは僕と同じくこのSNSのクライアントを自作している方ばかりで、その内容もクライアント開発に関することが多いので、他の開発者の方たちの過去の投稿をさかのぼって見ていたら、どうやらユーザーIDは投稿するIPアドレスから一意に決まることがわかりました。
また、固定IPでネット接続している方はいいのですが、僕の自宅の環境は固定IPではないのでコロコロとIPアドレスが変わります。
どうしたものかかなり悩みましたが特に解決策は見つからなかったので、投稿時のIPアドレスをlocalStorageに保存しておいて、IPアドレスが変わったらクライアント側で持っているユーザー情報を破棄するという対応でお茶を濁しました…。
なおIPアドレスの取得には下記のサービスを使っています。
useSWRInfinite
Twitter風のSNSなのでそのUIは無限スクロール一択ですよね。
SWRを使ってAPIリクエストをしているので、投稿テキストの一覧の取得にuseSWRInfinite hooksを使いました。
export const useTexts = (
limit: number = 20,
options: SWRInfiniteConfiguration = {}
): SWRInfiniteResponse<Text[], Error> => {
return useSWRInfinite((pageIndex, previousPageData) => {
if (previousPageData && !previousPageData.length) return null
return getTextsUrl(pageIndex * limit, limit)
}, options)
}
せっかくNext.jsで作っているので、最新20件をISRで取得、クライアント側でスクロールに応じて続きを取得するつもりで作りましたが、うまくいかなかったのですべてCSRで取得するように変えました。
このあたりはまた時間ができたら挑戦したいと思っています。
ダークモード
最近のウェブサイトは猫も杓子もダークモードを導入していて、ダークモード対応してないとそれだけでイケてないかのような空気を勝手に感じていたので、今回初めて挑戦してみました。
なお個人的には機能自体の必要性をほとんど感じていません…。
ライトモード(左)とダークモード(右)
Tailwind CSSを利用しているのでダークモード対応も以下のように簡単にできました。
module.exports = {
// darkModeプロパティは 'media' か 'class' の値を指定可能
// - media: 端末の設定に合わせる
// - class: .darkクラスを持つ要素の配下にダークモードを適用する
darkMode: 'media',
}
const AppHeader: FC = () => (
<header className="bg-white dark:bg-gray-800">
// ...
</header>
)
Blockies
このSNSは特にユーザーアイコンを登録する機能はないようで、名前のみだと画面が寂しいのでBlockiesという文字列から画像を作成してくれるパッケージを使って、その画像をユーザーアイコンとしています。
作ってみた感想
サイトのロゴ
このサイトは「SOFEAP」という名前にしたのですが、これは元の記事のタイトルにある「エンジニア・プログラマにしか使えないSNS」をそのままDeepLで翻訳してみたら出てきた、「SNS only for engineers and programmers」という文の頭文字を取って並べたものです。
これを思いついたとき妙に気に入ってしまい、その後の開発への意欲が爆上がりしました。(そういうことありますよね!?)
その意欲も一段落し、とりあえず満足行くところまで実装できたのでこれを書きました。
まだAPI側には用意されてるけど実装できてない機能などもあるので、時間を見つけて育てて行きたいと思います。
Discussion