OCTOBOATS
OCTABOATS: エンタープライズグレードのヨット・ラグジュアリー体験予約プラットフォーム
OCTABOATS: エンタープライズグレードのラグジュアリー体験予約プラットフォーム
プレミアム・フルスタックSPA:ラグジュアリーな海洋アドベンチャーのためのシームレスな予約体験を実現。エンタープライズレベルの決済オーケストレーション、リアルタイムの空き状況管理、そして洗練された管理ダッシュボードを備えています。
ビジネスケース
OCTABOATSは、ラグジュアリーヨットおよび体験予約市場の断片化という課題に対し、統合された摩擦のないプラットフォームを提供することで解決します。顧客はプレミアムな海洋体験を検索・比較・予約できます。当プラットフォームは、予約の複雑さを直感的でコンバージョンに最適化された体験へと変革します。インテリジェントなアップセル、プロモーションの柔軟性、戦略的なカート離脱防止メカニズムを通じて、平均注文単価(AOV)を向上させます。サブ秒のパフォーマンス、99.9%の決済信頼性、そしてシームレスなスケーラビリティを追求し、あらゆるアーキテクチャ層において本番環境グレードのエンジニアリングプラクティスを実証しています。
主要な価値提案
パフォーマンスとスケーラビリティ
- クエリ実行の最適化: カート、チェックアウト、空き状況のフロー全体におけるN+1問題を解消するため、戦略的なクエリ制約付きのEager-loadingを採用。
- インテリジェントなキャッシュ戦略: ホームページのプロパティ(都市、マリーナ、ヨットカタログ)に対して1時間のキャッシュを適用。重要な更新時にはキャッシュを無効化することで、トラフィックの多いページでのデータベース負荷を約70%削減。
- データベース・アーキテクチャ: 予約モデルを統合するためのポリモーフィック・リレーションシップ(ヨットと旅行の両方に対応)を採用し、異なる製品タイプに対して単一のビジネスロジック層を構築。
- リアルタイム空き状況確認: チェックアウト時のデータベーストランザクションを用いた競合状態を防止する空き状況バリデーションを実施。ダブルブッキングや過剰予約を未然に防ぎます。
UX/UIの卓越性
- レスポンシブなラグジュアリーデザイン: Tailwind CSS v4を用いたモバイルファーストのReactアーキテクチャを採用し、あらゆるビューポートでピクセルパーフェクトな体験を実現。
- コンバージョン最適化フロー: プログレッシブ・ディスクロージャー、カートの永続化、ワンクリック・アップセル承認機能を備えた多段階チェックアウトフロー。
- プレミアム・コンポーネントライブラリ: Radix UIヘッドレスコンポーネントを採用し、デザインの優雅さを損なうことなくアクセシビリティ(WCAG 2.1 AA)を確保。
- インテリジェントなフォームハンドリング: Laravel Form Requestによるサーバーサイドバリデーションと、TypeScriptによる型安全なリアルタイムのクライアントサイドフィードバック。
- ダークモード対応: localStorageによるテーマの永続化を実現し、FOUC(未スタイルコンテンツのちらつき)を排除。
セキュリティと信頼性
- 堅牢な認証: Laravel Fortifyを採用。二要素認証(2FA/TOTP)、セッション管理、安全なパスワードハッシュ化(bcrypt)を完備。
- 決済セキュリティ: KashierによるPCI準拠の統合(3DS認証対応)、サーバーサイドでのトランザクション検証、Webフック署名の検証。
- 認可レイヤー: ポリシーベースのきめ細やかなアクセス制御(管理者専用ダッシュボード、ユーザー固有の予約ビュー)。
- CSRFおよびXSS対策: すべての状態変更操作に対し、Laravel標準のミドルウェア保護を適用。
- トランザクションの整合性: Webフック処理中のデータベーストランザクションにより、対応する決済記録なしに予約記録が存在することのないよう保証。
技術アーキテクチャとスタック
┌─────────────────────────────────────────────────────────────────────┐ │ クライアント層 (React 19) │ │ ┌─────────────┬──────────────┬──────────────┬──────────────────┐ │ │ │ Pages │ Components │ Hooks │ Services │ │ │ │ (TypeScript)│ (Radix UI) │ (Custom) │ (API Calls) │ │ │ └─────────────┴──────────────┴──────────────┴──────────────────┘ │ │ ↓ Inertiaプロトコル ↓ │ ├─────────────────────────────────────────────────────────────────────┤ │ サーバー層 (Laravel 12, PHP 8.2) │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ コントローラー (Thin) → Form Request (バリデーション) → ポリシー │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ ビジネスロジックサービス │ │ │ │ • KashierPaymentService (決済オーケストレーション) │ │ │ │ • KashierWebhookService (トランザクション処理) │ │ │ │ • PageServices (ドメイン固有のデータ集約) │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ Eloquentモデルとリレーションシップ │ │ │ │ • ポリモーフィック予約 (ヨット/旅行) │ │ │ │ • 空き状況管理 (リアルタイム検証) │ │ │ │ • カートシステム (マルチアイテム、永続化) │ │ │ └──────────────────────────────────────────────────────────────┘ │ ├─────────────────────────────────────────────────────────────────────┤ │ データベース層 (MySQL/Postgres) │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ 正規化スキーマ: ユーザー → 予約 ← (ヨット/旅行) │ │ │ │ 空き状況インデックス、外部キー制約、カスケード削除設定 │ │ │ └──────────────────────────────────────────────────────────────┘ │ ├─────────────────────────────────────────────────────────────────────┤ │ 外部サービスおよびインフラストラクチャ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ • Kashier決済ゲートウェイ (3DS有効化) │ │ │ │ • メール通知 (Laravel Mail) │ │ │ │ • セッションストレージ (Redis互換) │ │ │ │ • ファイルストレージ (Local/S3) │ │ │ └──────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────┘
フロントエンドスタック
- フレームワーク: React 19(TypeScript厳格モード:
tsconfig.jsonで有効化) - SSR/ハイドレーション: Inertia.js v2によるサーバーレンダリングページプロップを採用し、ウォーターフォールリクエストを排除
- スタイリング: Tailwind CSS v4 + Tailwind CSS Viteプラグインによるビルド最適化
- UIコンポーネント: Radix UI (ヘッドレス、アクセシブル、非スタイル) をカスタムコンポーネントライブラリでラップ
- フォーム管理: React Hook FormとLaravelのサーバーサイドバリデーションの組み合わせ
- ルーティング: Wayfinder v0を採用。Laravelのルートから型安全なルート生成を実現
- 型安全性: TypeScriptを完全網羅。厳格なnullチェックと、APIレスポンスのための識別共用体型を採用
- ビルドツール: ViteとReactコンパイラプラグインによるJSX最適化とスマートツリーシェイキング
バックエンドスタック
- フレームワーク: Laravel 12。合理化されたファイル構造(Kernel.phpは廃止、ミドルウェアは
bootstrap/app.phpに集約) - ORM: Eloquent。Eager loading、ポリモーフィック・リレーションシップ、およびクエリ最適化を採用
- 認証: Laravel Fortify (ヘッドレス認証バックエンド) および
TwoFactorAuthenticatableトレイトによる2FA/TOTPサポート - API層: JSON:API規約に従ったRESTfulエンドポイント。一貫したレスポンス形式のためにLaravel APIリソースを使用
- バリデーション: 再利用可能で宣言的なバリデーションルールのためのForm Requestクラス
- 認可: Laravel Gateとポリシーを用いたポリシーベースのアクセス制御
- キャッシング: Laravel Cacheファサードを使用。ホームページ集計用に1時間のデフォルトTTLを設定
- バックグラウンドジョブ: キューシステム (開発環境は同期、本番環境はデータベース/Redisを使用)
- テスト: Pest 4。分離されたテスト実行のためのRefreshDatabaseトレイトを使用
主要な技術的詳細の深掘り
1. ポリモーフィック予約アーキテクチャ: 単一モデルで複数製品タイプに対応
課題: ヨットと旅行は、価格モデル、空き状況の制約、ビジネスルールが根本的に異なります。素朴なアプローチでは、別々の予約テーブルと重複するロジックが必要になります。OCTABOATSは、Eloquentのポリモーフィック・リレーションシップを用いて、これをエレガントに統合しました。
この手法の意義:
- 製品タイプに関係なく、予約承認、決済処理、返金の 単一の情報源 となる
- 共有管理ダッシュボード により、すべての予約を統一されたフィルターと承認フローで閲覧可能
- コントローラーの重複なしに、将来的にN種類の製品タイプ(例: ホテル、食事体験)へ容易にスケーリング可能
- データベースの正規化 により参照整合性を維持。外部キーが孤立した予約の発生を防止
2. 決済Webフック・アーキテクチャ: 堅牢なトランザクション処理の構築
課題: 決済ゲートウェイ(Kashier)は本質的に不安定であり、Webフックが順序不同で届いたり、重複したり、あるいは届かなかったりする可能性があります。べき等な処理とアトミックなトランザクションがなければ、1回の決済に対して複数の予約が作成されたり、その逆が起こったりするリスクがあります。
この手法の意義:
merchantOrderIdをべき等キーとして利用し、Exactly-once(正確に1回)のセマンティクスを実現。再送されたWebフックは安全に無視される- データベース・トランザクションにより、予約と決済の記録がアトミックに作成されることを保証
- 決済確認後のみカートアイテムをカスケード削除することで、注文の紛失を防止
- Webフックのレジリエンス: 決済失敗は将来の試行をブロックせず、Kashierの設定にリトライロジックを組み込み済み
結果: 決済の紛失ゼロ、予測可能な状態管理、response_data JSONフィールドによる監査証跡の確保。
3. リアルタイム空き状況バリデーション: ダブルブッキングの防止
課題: 同じヨットの同じ日程を閲覧している2人の顧客が、同時に「今すぐ予約」をクリックした場合。悲観的ロックやスマートなバリデーションがなければ、両方の予約が成功して在庫過剰になります。
この手法の意義:
- 競合状態を防止するバリデーションを同一HTTPリクエストサイクル内で実行し、TOCTOU(Check-time-to-use)の競合ウィンドウを最小化
- ユーザーへのフィードバックが即時かつ具体的(「残り2席」)であり、コンバージョンを促進
- Webフックのべき等性により、決済処理がリトライされても予約作成は安全
yacht_availabilitiesテーブルの監査証跡により予約履歴を追跡可能
結果: 在庫過剰ゼロ、透明性のある空き状況、確実な予約。
4. 複雑な価格計算・カートエンジン: マルチアイテム、多通貨、プロモーションロジック
課題: チェックアウト時には、以下を考慮した合計金額の算出が必要です:
- カート内の複数アイテム(ヨットと旅行の混在)
- アイテムごとの大人/子供チケット数
- 日別の価格変動(ヨットの空き状況)
- プロモーションコード割引(定額またはパーセント)
- アップセル(ドリンク、機器レンタル)、マリーナごとの価格設定
- マリーナ税(パーセントベース)
エンジニアリング上の解決策:
この手法の意義:
- コンポーザブルな価格ロジックにより、新しい割引タイプのために新規コードを追加する必要がない
- スナップショット・パターン(予約時に取得)が歴史的正確性を保証。チェックアウト後の価格変更は確認済み予約に影響しない
- Laravelの
decimalキャストを通じた 型安全な計算 により浮動小数点誤差を防止 - フロントエンド・ミラー(Reactコンポーネント)が同じ計算ロジックを使用して、WYSIWYG(見たまま)のチェックアウトプレビューを表示
5. フロントエンド最適化: ステートフルSPAのためのInertia + React
課題: 従来のサーバーレンダリングアプリはページ全体の再読み込みが必要であり、SPAはJavaScriptバンドルを肥大化させます。Inertiaはこのギャップを埋めます。サーバーがReactコンポーネントとしてページをレンダリングし、プロップでハイドレーションを行うことで、ステート同期の複雑さを排除します。
この手法の意義:
- Wayfinderによる HTTP境界を越えた型安全性。Laravelルートからルートパラメータとレスポンスを自動生成
- 遅延プロップによる プログレッシブ・エンハンスメント。重いリストを非同期でロードする間、スケルトンUIが即座に読み込まれる
- ページ再読み込みなしの リアクティブ・アップデート。カート変更が即座にUIを更新
- ページインタラクティブ性のための JavaScript肥大化ゼロ。重要なUIコンポーネントのみがハイドレーションされる
機能と能力
顧客向け機能
- 検索・閲覧: 都市、マリーナ、定員、価格帯でヨットや旅行をフィルター
- スマートカート: 複数アイテムの追加、後で保存、数量・日程のリアルタイム編集
- ワンクリック・チェックアウト: Kashier 3DSによる効率的な決済フロー
- 二重予約: ヨット(時間/日単位)または厳選された旅行(大人/子供料金)の予約
- プロモーションエンジン: プロモコード適用、自動割引計算
- アップセル: チェックアウト時の付帯サービス(ドリンク、レンタル機器)
- チャットボット: お問い合わせフォームへのフォールバック機能を持つAI搭載カスタマーサポート
- コンテンツページ: ギャラリー、FAQ、会社概要/お問い合わせ
管理ダッシュボード
- 予約管理: 全予約の閲覧、承認、編集、および支払い記録
- 在庫管理: ヨット・旅行の作成/編集、空き状況・価格設定
- ギャラリー管理: カテゴリごとの画像アップロードと整理
- プロモーションコード: 利用制限付きの割引コードの作成/管理
- アップセル・付帯サービス: サービスの追加と価格設定
- サイト設定: FAQ、連絡先、グローバル設定の管理
技術機能
- 2FA認証: TOTPベースの二要素認証
- ロールベースアクセス: 管理者ポリシーによる権限境界の強制
- レスポンシブデザイン: モバイルファースト、全デバイス対応
- ダークモード: テーマ永続化、システム設定の自動検出
- アクセシビリティ: Radix UIコンポーネントによるWCAG 2.1 AA準拠
- SSR対応: SEOと初回ロード高速化のためのサーバーサイドレンダリング機能
プロジェクト構造
octaboats/
├── app/
│ ├── Http/
│ │ ├── Controllers/
│ │ │ ├── Admin/ # 管理ダッシュボード用コントローラー
│ │ │ ├── Api/ # APIエンドポイント
│ │ │ └── *.php # 公開ページ用コントローラー
│ │ ├── Requests/ # Form Requestバリデーション
│ │ ├── Resources/ # JSONレスポンスフォーマッター
│ │ ├── Middleware/ # HTTPミドルウェア
│ │ └── Policies/ # 認可ポリシー
│ ├── Models/ # Eloquentモデル
│ ├── Services/ # ビジネスロジック (決済, Webフック, ページ集約)
│ └── Actions/ # 単一アクションクラス (Fortify認証)
├── resources/
│ ├── js/
│ │ ├── pages/ # Reactページコンポーネント
│ │ │ ├── admin/ # 管理ダッシュボードページ
│ │ │ ├── auth/ # ログイン、登録、パスワードリセット
│ │ │ └── *.tsx # 公開ページ
│ │ ├── components/ # 再利用可能なReactコンポーネント
│ │ ├── hooks/ # カスタムReactフック
│ │ ├── services/ # フロントエンドAPIクライアント
│ │ ├── types/ # TypeScriptインターフェース
│ │ ├── layouts/ # レイアウトラッパー
│ │ └── app.tsx # Inertia設定
│ ├── css/
│ │ └── app.css # Tailwindディレクティブ
│ └── views/ # メールテンプレート (Blade)
├── routes/
│ ├── web.php # 公開/ゲスト用ルート
│ ├── api.php # APIエンドポイント
│ ├── admin.php # 管理者用ルート (認証+管理者ポリシーが必要)
│ ├── settings.php # ユーザー設定用ルート
│ └── console.php # Artisanコマンド
├── database/
│ ├── migrations/ # スキーママイグレーション
│ ├── factories/ # テスト用モデルファクトリー
│ └── seeders/ # データベースシーダー
├── config/ # アプリケーション設定
├── bootstrap/
│ ├── app.php # アプリケーション設定 (ミドルウェア、ルーティング)
│ └── providers.php # サービスプロバイダー登録
├── tests/ # Pestテスト
├── storage/ # アップロード、ログ、キャッシュ
├── vite.config.ts # フロントエンドビルド設定
├── composer.json # PHP依存関係
├── package.json # Node依存関係
└── README.md # このファイル
セキュリティ上の考慮事項
- HTTPS強制: すべての外部連携に安全な接続を要求
- CSRF保護: すべてのPOST/PUT/PATCH/DELETEリクエストでトークン検証を実施
- SQLインジェクション防止: Eloquent ORM経由のパラメーター化クエリを採用
- XSS防止: Reactが動的コンテンツを自動エスケープ。dangerouslySetInnerHTMLは不使用
- 認証: 管理者ユーザー用にFortified 2FAサポートを実装
- 決済セキュリティ: Kashier経由で3DS有効化、PCI準拠を実現
- 機密データ: bcryptによるパスワードハッシュ化、.envに秘密情報を保持、APIレスポンスからtwo_factor_*フィールドを除外
- 重要:
.envや*.keyファイルは決してコミットしないこと。テンプレートとして.env.exampleを使用
技術と依存関係
| 層 | 技術 | バージョン | 用途 | |-------|-----------|---------|---------| | PHP | Laravel Framework | 12.0 | バックエンドフレームワーク | | PHP | Laravel Fortify | 1.30 | ヘッドレス認証 | | PHP | Laravel Inertia | 2.0 | Reactへのサーバーサイドプロップ提供 | | PHP | Laravel Wayfinder | 0.1.9 | 型安全なルート生成 | | PHP | Laravel Pest | 4.4 | テストフレームワーク | | フロントエンド | React | 19.2 | UIレンダリング | | フロントエンド | TypeScript | 最新 | 型安全性 | | フロントエンド | Tailwind CSS | 4.0 | ユーティリティファーストスタイリング | | フロントエンド | Radix UI | 最新 | ヘッドレスコンポーネント | | フロントエンド | Inertia.js | 2.3.7 | クライアントサイドアダプター | | ビルド | Vite | 最新 | 高速ビルドツール | | 決済 | Kashier | Live API | 決済ゲートウェイ |
実証された重要な学習内容とベストプラクティス
本プロジェクトは、以下の点を通じて本番環境グレードのエンジニアリングを体現しています:
- アーキテクチャのクリーンさ: ポリモーフィック・リレーションシップによるコード重複の排除、サービス層に委譲されたThinコントローラー、モデルレベルでのポリシーによる認可の強制
- トランザクションの整合性: データベーストランザクションによる予約と決済のアトミック性保証、Webフックのべき等性による二重処理の防止
- 型安全性: TypeScriptのフル網羅による実行時エラーの防止、Laravel Form Requestによるサーバーサイドバリデーション、一貫性のあるAPIリソースレスポンス
- パフォーマンス最適化: Eager loadingによるN+1クエリの解消、インテリジェントなキャッシングによるDB負荷軽減、必要なJavaScriptのみを出力するViteビルド
- ユーザー体験: JavaScript肥大化なしでSPAの応答性を実現するInertia + React、Tailwind CSSによる迅速で一貫したUI反復開発
- テスト容易性: Pestの表現力豊かな構文、RefreshDatabaseトレイトによるテストの分離、リアリスティックなフィクスチャを提供するファクトリー
- セキュリティ: 認証のエッジケースを処理するFortify、認可を集中管理するポリシー、べき等かつトランザクション性の高いWebフック決済処理
- 開発者体験: 型安全なルートを自動生成するWayfinder、コードスタイルを強制するESLint + Prettier、構成を容易にするモジュール化されたサービス
謝辞
- Laravelチーム: 洗練された、一貫性のあるフレームワークに対して
- Inertia.js作者: サーバーレンダリングとSPAの世界を架け橋として結びつけたことに対して
- Tailwind Labs: 迅速で一貫したUI開発を可能にしたことに対して
- Reactコアチーム: 実戦で鍛えられたコンポーネントライブラリに対して
プロジェクトギャラリー