オンラインのうちに準備して、オフラインでも迷わない待ち合わせを
Overview
プロジェクト情報
開発期間
2026.03
クライアント
個人開発
役割
設計・開発(フルスタック)
チーム構成
1名
Outline
概要
「迷ったらここに集合しよう」をシンプルに伝えるための待ち合わせ Web アプリ。事前に地図と目的地をダウンロードしておくことで、電波のない環境でも地図とピンをそのまま確認できる。スマホ操作に不慣れな友人や家族でも直感的に使えるシンプルな UI を目指して設計・開発した。
Objectives
目的・背景
開発背景
待ち合わせの際、電話や文字より地図上のピン一つで伝えるほうがシンプルで確実だと感じていた。一方で、電波環境が不安定な場所での利用や、デジタルに不慣れな相手への配慮も必要だと考え、オフライン対応のシンプルな待ち合わせアプリとして開発した。
届けたいユーザー
スマホ操作に慣れていない友人・家族も含む幅広いユーザー。難しい操作なしに、地図と目的地をすぐ確認できることを最優先にした。
Key Features
主な特長
地図・目的地のオフライン対応
オンライン時に地図タイルと目的地情報を IndexedDB にキャッシュ。電波のない環境でもダウンロード済みの地図とピンをそのまま閲覧できる。

ワンタップで地図をダウンロード
用意された地図をタップするだけで端末に保存できる。複雑な操作を排除し、誰でも迷わず準備できる導線を設計した。
目的地のマーキング・共有
事前に目的地をピンで登録し、URLで共有できる。受け取った側もタップするだけで同じ地図・目的地を確認・保存できる。
Tech Stack
技術スタック
アーキテクチャ図

フォルダ構成
. ├── assets │ └── icon │ ├── attraction.svg │ ├── cafe.svg │ ├── fastfood.svg │ ├── index.ts │ ├── restaurant.svg │ ├── shop.svg │ └── toilet.svg ├── components │ └── ui │ ├── Header.tsx │ └── Layout.tsx ├── config │ └── mapStyle │ ├── constants.ts │ ├── disneylandMapStyle.ts │ ├── index.ts │ ├── mabashiMapStyle.ts │ └── types.ts ├── features │ ├── home │ │ ├── components │ │ │ ├── __tests__ │ │ │ │ └── Home.spec.tsx │ │ │ ├── CacheClearSection.tsx │ │ │ ├── Card.tsx │ │ │ ├── Cards.tsx │ │ │ ├── Home.tsx │ │ │ ├── HomeHeader.tsx │ │ │ ├── HomeLoading.tsx │ │ │ └── NoData.tsx │ │ └── hooks │ │ ├── __tests__ │ │ │ └── useHome.test.ts │ │ └── useHome.ts │ └── map │ ├── application │ │ ├── DestinationMarkerService.ts │ │ ├── IDestinationMarker.ts │ │ ├── IDestinationMarkerFactory.ts │ │ ├── IMap.ts │ │ └── MarkerStoreActions.ts │ ├── components │ │ ├── Map.tsx │ │ ├── MapLoading.tsx │ │ └── MapNotFound.tsx │ ├── domains │ │ ├── entities │ │ │ ├── __tests__ │ │ │ │ ├── Destination.test.ts │ │ │ │ └── Map.test.ts │ │ │ ├── Destination.ts │ │ │ ├── DestinationMarker.ts │ │ │ └── Map.ts │ │ ├── repositories │ │ │ ├── DestinationRepository.ts │ │ │ └── MapRepository.ts │ │ └── valueObjects │ │ ├── __tests__ │ │ │ └── LngLat.test.ts │ │ └── LngLat.ts │ ├── hooks │ │ ├── __tests__ │ │ │ └── useMapEvent.test.tsx │ │ └── useMapEvent.ts │ ├── infrastructure │ │ ├── __tests__ │ │ │ └── SupabaseMapRepository.test.ts │ │ ├── maplibre │ │ │ ├── DestinationMarkerFactory.ts │ │ │ ├── MapFactory.ts │ │ │ ├── MaplibreDestinationMarker.ts │ │ │ ├── MaplibreMap.ts │ │ │ └── marker.module.css │ │ └── supabase │ │ ├── destinationMapper.ts │ │ ├── mapMapper.ts │ │ ├── SupabaseDestinationRepository.ts │ │ └── SupabaseMapRepository.ts │ ├── loader │ │ ├── __tests__ │ │ │ └── mapLoader.spec.tsx │ │ └── mapLoader.ts │ ├── utils │ │ ├── marker.ts │ │ └── userMarker.ts │ └── constants.ts ├── lib │ ├── indexedDB │ │ ├── constants.ts │ │ ├── database.ts │ │ └── types.ts │ └── supabase │ ├── schema.ts │ └── supabaseClient.ts ├── router │ ├── __tests__ │ │ └── NotFound.spec.tsx │ ├── AppRouteProvider.tsx │ └── NotFound.tsx ├── store │ └── useMapStore.ts ├── styles │ └── index.css ├── main.tsx └── serviceWorker.ts
工夫したこと
Service Worker によるオフラインキャッシュ設計
fetch インターセプトを活用し、地図タイルと目的地データをオンライン時に IndexedDB へ保存。ネットワーク状態に関わらず一貫した体験を提供できるよう設計した。
TDD とクリーンアーキテクチャを意識した設計
ドメインロジックを TDD で実装し、テストコードが設計ドキュメントとして機能するよう意識した。レイヤードアーキテクチャとフィーチャーアーキテクチャを組み合わせることで、責務の分離を保ちながらファイル構成の見通しを高めた。
Next Step
今後の展望
Link
外部リンク