JP / EN / PT
Kaimono
https://p0r6iz89.cloud
Github
日常の買い物で、こんなふうに感じたことはありませんか?
出費を1つずつ記録するのは面倒で、合計も把握しづらい。情報が増えるほど判断に迷って、結局なかなか前に進めない。
この課題を解決するために、買い物計画と予算管理に特化した Web アプリ Kaimono を作りました。
Kaimono は、次の3機能を中心に設計しています。
買い物リスト管理
日用品を管理するシンプルな To-do。
「今買うもの」を支出管理と同じ場所で扱えるため、アプリの入口として機能します。
予定品管理
日用品より高額で、購入前に計画と予算判断が必要なアイテムを管理します。
プロジェクト管理(コア機能)
予定品を目的ごとにまとめ、プロジェクト単位の総予算を可視化します。
例: 部屋の模様替え(カーペット、照明、観葉植物など)。
各アイテムに URL も保存できるので、比較中の商品にすぐ戻れます。
さらに、Kaimono ではサブドメインベースのマルチテナント構成を採用し、他ユーザーのデータが見えないように分離しています。
team.p0r6iz89.cloud
team がサブドメインp0r6iz89.cloud がメインドメイン共同利用したい場合は、Invitations ページからメンバー招待できます。
このプロジェクトで最優先したのは、本質的な課題(計画と予算を見える化して管理しやすくすること)を、できるだけシンプルに解くことでした。
以前は Django + React も使っていましたが、小規模アプリでは「フロントを作りつつ API を都度調整する」コストが開発速度を落とす感覚がありました。
そのため Kaimono では、Server Actions から Prisma 経由で直接 DB とやり取りする構成を採用しています。これによりフロントとバックエンド間の摩擦を減らし、実装を一貫させました。
結果として、安全な CRUD と 実装の一貫性 を両立できています。
Kaimono はオープンソースで、npm + Docker でローカル起動できます。
npm install
docker compose up -d db
npx prisma migrate dev
npm run dev
リンク:
ローカル URL:
http://localhost:3000/jahttp://team.localhost:3000/jaこの構成では Docker Compose は PostgreSQL(db サービス)のみ起動し、Next.js アプリ本体は npm run dev でローカル実行します。
TypeScript の型と整合性を守りながら、読みやすいコードを書くところから始めました。
最初の大きな課題は、誰でも使える形でマルチテナントを導入することでした。
より手早い選択肢(例: Clerk のマルチテナント機能)もありましたが、学習と制御性を重視して、サブドメイン + middleware を自前で実装しました。
middleware.ts のリクエストフローは次の通りです。
handleI18nRouting を通し、/en・/ja・/pt-BR のロケール付きルートに正規化。req.auth?.user と公開パスを判定。
/{locale}/login へリダイレクト/login にアクセス => /{locale}/ へリダイレクトteam.localhost や team.example.com からテナントサブドメインを抽出。/{locale}/s/{subdomain}{rest} に rewrite。この rewrite によって、ユーザーには URL 構造を意識させずに、1つの App Router 構成でマルチテナントを維持できます。 サーバー境界では Zod で入力を検証し、予測可能なエラー状態を返しています。
middleware.ts Request Flow
今後も、URL ベースの OAuth フロー と i18n がマルチテナント設計を壊さないことを前提に、機能拡張を続ける予定です。
現在「Essentials」や「Planned items」は手入力が必要です。オートコンプリートでも改善できますが、さらに入力負荷を下げるために、写真から商品情報を自動入力する機能を検討しています。例: