はじめに
こんにちは!
WEBアプリケーションエンジニアとして活動しているPOMです。
元々はPHPやJavaScriptなどをメインとしていましたが、
今年3月からはアウトプットコミュニティであるJISOUに参加し、現在はReactやTypeScriptでの開発を行っています。(なので、モダンフロントエンド開発の歴は浅めです)
突然ですが・・・
いつもとは違う美容室に行った時に美容師さんから「前、どんなカラーで染めましたか?」と聞かれたことはありませんか?
私自身たまに聞かれて(意外と)数ヶ月前のことだと思い出せないことが個人的にあり、写真フォルダから探そうとしてもすぐ見つからなかったりという経験がありました。
また、毎月自分の中で美容にかけるお金の目安があるものの、結局どれくらい使っているのか?を一目で可視化できると良いなと思っていました。
そこで、
「美容の過去の履歴(記憶や写真)がすぐに出てこない」
「美容費がいつの間にか膨らんでいる」
これらの悩みを解決する管理アプリを作ることにしました。
今回は制作期間およそ1ヶ月で、完全に自分のアイデアを基にした
美容記録×予算管理アプリ「Bilog」を開発してみました!
Bilogについて
リポジトリはこちらになります。
ストレージやメール認証において無料枠だと制限(後述)があるため、現時点でアプリの一般公開はしておりません。
まずは家族や友人に使ってもらう形で考えています!
技術スタック
| 領域 | 技術 |
|---|---|
| ランタイム | Node.js 22 / npm |
| フロントエンド | React 19, TypeScript |
| ビルド | Vite |
| UI | Tailwind CSS v4, shadcn/ui v4 |
| DB / Auth / Storage | Supabase (PostgreSQL) |
| ホスティング | Firebase Hosting |
| テスト | Vitest, React Testing Library |
| CI/CD | GitHub Actions |
| その他ライブラリ | react-hook-form, zod, TanStack Query, react-router-dom, Recharts, react-select |
機能
機能としては大きく分けて以下になります。
- 新規登録・ログイン(メール認証)
- 今月の予算に対しての使用額・残り金額を表示
- 美容履歴ビュー
- 美容記録登録・一覧表示
- 施術前のbefore/After写真比較
- 予算設定・一覧表示
新規登録・ログイン(メール認証)
最初に「Bilog」アプリにアクセスすると、まずはログイン画面が表示されます。
初めてのユーザーは「アカウントをお持ちでない方はこちら」を押下して、
下記画面にて新規登録を行う必要があります。
必要項目を入力すると、入力したメールアドレスに認証用のメールが届くので、
メール内のボタンを押下することでログインすることができます。
今回、メール認証機能にはSupabase Authを利用しました。
併せてパスワードを忘れた方のための再設定機能も実装しています。
ただし、Supabaseはデフォルトだとメール送信に上限があり、1時間に数通しか送れません...。SupabaseのSMTP設定を別のプロバイダに向けることで上限を引き上げることができます。
Resendだとどうやらカスタムドメインの取得が必要みたいなので、今回私は無料の範囲内で実現可能なGmailにてSMTP設定しました。
今月の予算に対しての使用額・残り金額を表示
解決したい課題の1つである美容費の可視化として、
- 今月の予算に対しての使用額や残額
- カテゴリ別で美容費にかけた金額の割合
を表示するようにしました。
予算額を超過している場合は、画面上に赤く表示される他、
アプリ内でアラート(トースト)が出てユーザーに通知されます。
カテゴリ別グラフにはRechartsというライブラリを使用しています。
美容履歴ビュー
解決したい課題のもう1つである過去の美容記録として、
施術後の写真(直近10件)を時系列でカテゴリ別に並べ、
自分の髪色や髪型・ネイルなどの変遷が一目で分かるようになっています。
なお、本アプリ内のカテゴリとしては、
「ヘア」「ネイル」「まつ毛」「エステ」「医療」に絞って用意しています。
(今後、ユーザー側でカテゴリを追加・編集できる機能があっても良さそうです。)
枚数が多くなると横スクロール形式で見ることができます。
美容記録登録・一覧表示
美容記録を登録し、記録一覧を見ることができます。
【登録画面】
入力項目の詳細はこちら
| 項目名 | 内容 | 必須 |
|---|---|---|
| カテゴリー | ヘア/ネイル/まつ毛/エステ/医療 | ✔️ |
| タイトル | 例)ハイライト+グレージュ | ✔️ |
| 詳細 | 例)ブリーチあり | |
| 金額 | かかった金額 | ✔️ |
| 実施日 | 実施した年月日 | ✔️ |
| 実施前の写真 | 実施する前の写真 | |
| 実施後の写真 | 実施した後の写真 | |
| 店舗名 | 実施した店舗名 | |
| 担当者名 | 担当した人の名前 |
画像の格納にはSupabase Storageを用いています。
設定は下記記事を参考にしました。
ただし、ストレージ容量はFreeプランで1GBまでとのことで、アプリを一般公開するのであれば運用面を考えると課金の必要性がありそうです。
【記録一覧】
年月単位でグルーピングし、カテゴリでフィルタリングすることもできます。
施術前のbefore/After写真比較
美容記録の詳細画面では、施術前後でどれくらい変わったか?の写真比較をすることができます。
仮に、片方or両方の写真が無くても違和感のないUIにしています。
併せて、当該画面内3点マークから美容記録の編集もしくは削除することができます。
予算設定・一覧表示
予算の設定と、今までの予算と使用額・残額を見ることができます。
【予算設定】
【予算一覧】
年月単位でグルーピングし、3点マークから当該年月の予算設定を編集もしくは削除することができます。
DB構成
logs:美容記録を格納するテーブル
next_interval_daysカラム(次回施術日までの間隔)は現時点では未使用です。今後の機能拡張で使用予定です。
salons:店舗名を格納するテーブル
addressカラム(店舗の住所), map_urlカラム(店舗のマップURL)は現時点では未使用です。今後の機能拡張で使用予定です。
staffs:担当者名を格納するテーブル
ratingカラム(担当者評価), notesカラム(評価メモ)は現時点では未使用です。今後の機能拡張で使用予定です。
budgets:予算設定を格納するテーブル
auth.users:Supabaseで自動生成されるテーブル
usersテーブルについては、こちらの記事が参考になります。
https://qiita.com/t-kurasawa/items/ebaa65b47d496f2f2819
他のアプリとの差別化ポイント
美容院などの美容関連のお店を探す/予約するアプリは存在しますが、
過去に焦点を当てて、髪型やヘアカラーなどを記録するアプリは(意外と)少ないです。
また、その上で美容費の予算管理もできるというのが差別化ポイントになります。
記録だけではなく、施術前後や以前までの髪型・髪色等との比較や履歴ビューが一目で分かる、という点が更なる差別化ポイントになります!
工夫した点
1. MVP(Minimum Viable Product)開発
今回は5つのMVPに分割し、各フェーズにおいてテストおよびCI/CDを行うことで、ユーザー価値のある「必要最小限の機能」を提供し続けることを意識しました。
以下のように、hackMDでTodoリストのようなものを作成し、1ヶ月で開発するためのタスク管理を行いました。
(自分で自分のマネジメントをした、という感じですね。
2. スマホ用とPC用でレイアウトを分ける
実際に美容院などに外出した際に、本アプリ「Bilog」を使用することが多いと想定し、基本的にはスマホユーザー向けのレイアウトとしており、例えばスマホではサイドバー表示にし、PCではヘッダーにナビゲーション表示としております。
もちろん、PC上で使用しても動作や表示に問題はないUIにしております。
3. UXを考慮した店舗名・担当者名のサジェスト機能
美容記録の登録において、店舗名や担当者名についてはreact-selectというライブラリを使って、候補から選択するか、候補にない場合は入力して追加できるように工夫しました。
もし、候補からしか選択できないようなセレクト形式にすると「まず店舗名や担当者名を別画面で登録してから記録する」という導線になるので、初回のユーザー体験が重くなると考え、候補or入力ができる実装にしました。
同じ店舗名や担当者名を毎回打つ手間や表記ゆれを低減するために、入力補完として過去に入力した店舗名や担当者名をサジェストするようにしています。
大変だったこと・気づき
1. DB関連の実装や設定
あとで大幅に変更することが無いように、開発当初にDBの設計・構成を固めてから実装に入るようにしました。外部キーやユニーク制約をどう付けるかなど、頭を悩ませながら設計しました。
(改めて、まだまだDB周りの知識不足を痛感しました・・・。
また、Supabase(PostgreSQL)のRLS設定やポリシー作成についても、しっかり設定しないと他のユーザーのデータが見えてしまうといったセキュリティ事故に繋がりますので、参考記事など見ながら実行しました。
2. スマホ特有のレイアウト崩れ
今回はReact、TypeScriptのアウトプットをメインとしているので、スタイリング(およびGitフローの自動化)についてはClaude Codeを活用したのですが、PC上では問題なく見えてもiPhone上で開くとレイアウトが崩れていたりして、プロンプトの内容を工夫して伝えるのに地味に苦戦しました。
もちろんAIに指示した際には、他の実装部分に影響を及ぼしていないか、こちらで確認・判断した上でacceptするようにしました。
今後もAIとは上手に付き合いながら開発していきたいです!
今後の展望
余裕があれば以下の機能も実装したいと思っておりますので、今後の展望として記載します。
- 店舗管理(店舗名、住所、マップURLなどを登録し、店舗を一覧表示)
- 担当者の満足度評価や施術を受けた際の感想メモ機能
- 次回施術日リマインダ(「そろそろ次の予約しませんか?」といった通知を前回からの経過日数を基に表示)
おわりに
自分の日常での体験や友人との会話を基に今回のアイデアを思いつき、形にすることができたのは非常に大きな経験になりました。
1ヶ月という決まった時間の中でユーザーへの提供価値を考えて、機能を(良い意味で)取捨選択しながら開発できたのではないかと思います。
次回の開発からはNext.js編!日々、頑張ります。
参考記事
JISOUのメンバー募集中!
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてください!
▼▼▼















