Alam Sawame

Webアプリ開発

JP / EN / PT

お仕事募集中

日常の買い物で、こんなふうに感じたことはありませんか?

出費を1つずつ記録するのは面倒で、合計も把握しづらい。候補が増えるほど判断に迷って、なかなか購入に進めない。

この課題に向き合うため、買い物の計画、予算の可視化、共同管理に対応した多言語 Web アプリ Kaimono を開発しました。


プロジェクト概要

  • プロジェクト種別: 個人開発 SaaS / ポートフォリオ
  • 担当: フルスタックを単独で実装
  • ステータス: 継続開発中
  • 主なテーマ: マルチテナント構成、安全な認証、共同作業、i18n 対応ルーティング
  • 技術スタック: Next.js 15、React 19、TypeScript、Prisma 6、PostgreSQL、Auth.js、Tailwind CSS、Zod

現在の実装

  • サブドメイン型ワークスペースとテナントデータ分離
  • OWNER、ADMIN、MEMBER のロールベースアクセス制御
  • 日用品、購入予定品、プロジェクト単位の予算管理
  • ワークスペース招待、コメント、いいね、メンバー管理
  • 公開商品 URL からの商品情報抽出
  • 任意で有効化できる TOTP 二要素認証とリカバリーコード
  • 不正利用対策を備えたログインユーザー向け問い合わせ機能
  • 英語、日本語、ポルトガル語対応
  • 16 モデル / 5 enum の Prisma スキーマ
  • PostgreSQL マイグレーションを含む Vercel デプロイ

主なワークフロー

日用品

日用品は、繰り返し購入するものや直近で必要なものを扱う軽量な買い物リストです。タイトル、価格、数量、購入状況を記録し、未購入分の支出を把握できます。

購入予定品

比較や予算検討が必要な商品には、優先度、商品 URL、画像、説明、コメント、いいね、関連プロジェクトなどの詳しい情報を保存できます。

プロジェクト

購入予定品を目的ごとにまとめ、合計予算を分かりやすくします。たとえば部屋の模様替えなら、照明、家具、装飾品の候補を1つのプロジェクトで整理できます。

共同管理

ワークスペースのオーナーと管理者は、メールでメンバーを招待できます。メンバーシップとテナントの検証はサーバー側で行い、別ワークスペースのデータへアクセスしたり移動したりできないようにしています。


AI による商品入力支援

すべての項目を手入力する代わりに、公開されている商品 URL を送信できます。Kaimono は構造化された商品メタデータを読み取り、AI でテキストを整え、有効な商品画像があれば取り込みます。

抽出処理には URL の安全性検証、リダイレクト回数とレスポンスサイズの制限、タイムアウト、任意のレート制限を実装しています。また、簡単なクレジット残高で利用回数を管理し、無制限の抽出リクエストを防いでいます。


認証とアカウント保護

Auth.js を利用し、GitHub、Google、メールのマジックリンクによるログインに対応しています。ユーザーはアカウント設定から TOTP 二要素認証を任意で有効化できます。

設定時には認証アプリ用 QR コードと、1回のみ使えるリカバリーコードを生成します。有効化したアカウントは、保護されたワークスペースへ進む前に二要素認証を完了する必要があります。


ワークスペースルーティング

本番環境ではワークスペースごとにサブドメインを利用します。

workspace.p0r6iz89.cloud

  • workspace がテナントを識別するサブドメイン
  • p0r6iz89.cloud がルートドメイン

middleware は、ロケール処理、認証確認、二要素認証、ワークスペースルーティングをまとめて扱います。

  1. リクエストを対応ロケール付きルートへ正規化。
  2. 未ログインユーザーを保護ページからリダイレクト。
  3. 二要素認証が有効なら認証チャレンジを要求。
  4. リクエストホストからワークスペースのサブドメインを抽出。
  5. 内部的に /{locale}/s/{subdomain} へ rewrite。

middleware.ts Request Flow

これにより、公開 URL を簡潔に保ちながら、1つの多言語 App Router 構成でワークスペースを管理できます。


技術的な判断

Server Actions と Prisma を採用し、各フォームのために個別の REST API を用意せず、型付きの検証とデータベース処理をページのワークフロー内で共有できる構成にしました。

テナントが所有する操作では、認証ユーザーとワークスペースのメンバーシップをサーバー側で必ず確認します。更新入力は Zod で検証し、複合リレーションによって別ワークスペースのプロジェクトへ購入予定品を割り当てられないようにしています。

特に難しかったのは、認証、ロケールルーティング、ワークスペースのサブドメインを1つの仕組みとして動かすことでした。この境界を自分で実装したことで、ホストベースルーティング、認可、安全な URL 処理、状態を持つ認証フローへの理解を深めました。


オープンソースとローカル起動

Kaimono は npm と Docker でローカル起動できます。

npm install
docker compose up -d db
npx prisma migrate dev
npm run dev

リンク:

ローカル URL:

  • メインアプリ: http://localhost:3000/ja
  • ワークスペースアプリ: http://workspace.localhost:3000/ja

Docker Compose では PostgreSQL を起動し、Next.js アプリ本体は npm run dev で実行します。