No updates detected yet. GitHub releases will appear here.
車旅のしおり。旅程と車中泊マップ
Loading the full README.
Read the full README ↗This is a Next.js project bootstrapped with create-next-app.
旅行計画の作成から実施までをサポートするウェブアプリケーションで、Google Maps 連携により効率的な旅程管理を実現します。カーナビゲーション(Android Auto・Apple CarPlay)との連携を前提に設計されており、旅行中の移動をスムーズにサポートします。
全国の車中泊スポット情報(トイレ・入浴施設、安全性、静けさなど)を地図で検索でき、気になるスポットは旅程に直接追加可能。ユーザー投稿機能により、コミュニティで情報を共有できます。
📱 Android アプリを Google Play で公開中: 車中泊スポットマップ|車旅のしおり(アプリのソースは別リポジトリ
tns-mobileで管理。詳細は後述の「モバイルアプリ(Android)」を参照)
34.1560076,132.3973073)をクリップボード経由で簡単インポート。ITINERARY_DRAFT_ALLOWED_EMAILS で指定)で、将来的にはプレミアム会員特典として提供予定です(プレミアム会員機能自体はまだ未提供)。詳細は ADR-0008 / ADR-0009 を参照。車中泊スポットを地図で手軽に探せる Android アプリ 「車中泊スポットマップ|車旅のしおり」 を Google Play で公開しています。
club.over40web.tabi.spots)tns-web)とは別リポジトリ tns-mobile で管理(Expo / React Native)。/api/v1/*)を利用して車中泊スポット情報を取得します。API は固定 API キーで保護されており、アプリ側は EXPO_PUBLIC_SPOTS_API_KEY、Web 側は SPOTS_API_KEY に同じ値を設定します(「モバイルアプリ向け API」の項および ADR-0006 を参照)。Google Maps とシームレスに連携することで、旅行計画から実際の移動までをスムーズにサポートします。
個人開発ながら実際のユーザーがいる本番サービスとして運用しており、思いつきではなく計測・比較検討に基づいて設計判断を行っています。主な判断は ADR(Architecture Decision Record) として記録しています。
%%{init: {'theme':'neutral'}}%%
flowchart LR
U["利用者 / Android アプリ"] --> CF["Cloudflare<br/>(プロキシ・キャッシュ・WAF)"]
CF --> T["Cloudflare Tunnel"]
T --> D["ConoHa VPS の Docker<br/>Next.js standalone"]
D --> M["MongoDB Atlas"]
D --> A["Auth0 (認証)"]
D --> MB["Mapbox (地図・ジオコーディング)"]
D --> LLM["Anthropic API<br/>(AI旅程ドラフト生成)"]
D -.-> S["Sentry (エラー監視)"]
D -.-> P["PostHog (アクセス解析)"]
出発地・目的地・泊数から旅程ドラフトを LLM で生成する機能。「実在しない場所をでっち上げる」という LLM 特有のリスクを、検索と検証をコード側に寄せることで抑えています。
$geoWithin)で実在する車中泊スポットを検索し、ユーザーの好み(ペルソナ)や車両制約でスコアリング・絞り込み。$inc)で二重実行を防止し、成功時のみ消費する「ポイント制」で従量コストを制御。詳細設計は ADR-0008(アーキテクチャ)・ADR-0009(コスト・アクセス制御)・ADR-0010(ポイント制)を参照。
無料枠(Vercel Hobby)の CPU 使用量が利用増加に伴い恒常的に超過するようになったため、複数の移行先を比較検討した上で ConoHa VPS + Cloudflare Tunnel 構成へ移行(2026-09-20)。
| 検討した選択肢 | 見送った理由 |
|---|---|
| Cloudflare Workers | PoC で Mongoose の共有接続が並列アクセス時に不安定。データアクセス層の書き換えが必須かつ Worker サイズが無料枠を超過 |
| Netlify | 試験デプロイで日本からの応答速度が実用上厳しく、リージョン選択には有料プランが必要 |
| 自宅ミニPC | セルフホスト自体は検証済みだが、初期費用とVPSとの損益分岐が約4年後。停電・回線障害・セキュリティリスクを自宅で負うことになる |
| Vercel Pro | 運用の手間は最小だが、利用量に応じた課金で収支を予測しづらい(広告収入主体の小規模サービスのため) |
移行前にアプリ側の CPU 削減(詳細ページの ISR 化、トップページのクエリキャッシュ、地図操作時の不要な RSC リクエスト削減)にも取り組んでおり、インフラ変更の前にアプリ側でできることを尽くす判断をしています。DNS の切り替えのみで Vercel へ即時ロールバックできる構成にして移行リスクを抑えました。詳細は docs/self-hosting/migration-plan.md を参照。
updatedAt の比較で古いキャッシュを検出する stale-while-revalidate 方式(src/lib/itineraryCache.ts)。Content-Security-Policy は、広告(AdSense)や地図などサードパーティ接続先が多く「最初から全ブロック」では本番が壊れるリスクが高いため、段階的に適用しています。
Content-Security-Policy-Report-Only で本番稼働させ、違反レポートを Sentry に集約して観測。base-uri / object-src / frame-ancestors / form-action)だけを Content-Security-Policy(ブロック)として先行適用。ブラウザは複数の CSP ヘッダーを独立に評価するため、実運用への影響なく段階適用が成立します。本番環境では Mongoose の autoIndex を無効化しています(サーバーレス的なコールドスタートのたびに索引同期が走るのを避けるため)。そのため索引追加はコードの schema.index() だけでは本番に反映されず、専用スクリプト(scripts/sync-indexes.cjs)でドライラン確認後に明示的に同期する運用にしています。ユニーク制約は索引だけに頼らずアプリケーション層でも重複チェックを行い、索引未作成環境でも制約が機能するようにしています。
This is the beginning of the README. Read the rest at the original. Read the full README ↗