OpenAIExpoJan 6, 2026, 2:30 PM

The offline first, multilingual audio tour app built with Expo

A condensed section focused on the key takeaways first.

Original Post

Quick Digest

Summary

A condensed section focused on the key takeaways first.

openaienmodel: gpt-5-mini-2025-08-07

Kuratour — offline‑first multilingual audio tours built with Expo

Key Points

  • Offline-first with predownloaded assets
  • SQLite with versioned migrations
  • High-accuracy GPS + expo-audio for hands-free tours

Summary

Kuratour is an offline‑first, multilingual audio tour app built entirely with the Expo SDK. It delivers GPS-triggered, hands‑free audio narration and offline maps by pre‑downloading assets (map tiles, images, audio), storing metadata and progress in SQLite, and switching automatically between online/offline modes. The app integrates expo-location for high‑accuracy tracking, expo-file-system for mirrored local storage, expo-sqlite for versioned metadata, and expo-audio for layered multilingual playback.

Key Points

  • Architecture

    • Entire app built on Expo SDK (new architecture) using first‑party modules and community packages.
    • Core modules: expo-location, expo-file-system, expo-sqlite, expo-audio, expo-video, expo-splash-screen, expo-application, expo-apple-authentication, @rnmapbox/maps.
  • Offline strategy

    • Pre-download map tiles, audio, and images into the app Documents directory and store local URIs in SQLite.
    • Mirror remote directory structure locally to simplify lookups and playback.
    • Save tour metadata and visited locations in a versioned SQLite schema; use migrations for schema changes.
  • Data integrity and upgrade handling

    • Detect app version changes with expo-application and trigger a Content Validation Bridge to re-verify files.
    • Iterate offline tours and confirm each asset exists; queue background re-downloads if files are missing (addresses iOS Documents-directory edge cases).
  • Location and UX

    • Implement a high‑accuracy background location watcher with Location.watchPositionAsync for precise, hands‑free triggers (timeInterval, distanceInterval tunable).
    • Use a custom useOfflineDetector hook (with useFocusEffect) to prefer local SQLite data when a tour screen is focused.
  • Asset orchestration

    • Sequential download flow: directions → main imagery → per-location audio/background tracks; then persist file URIs back to SQLite.
    • Use expo-file-system utilities (Directory/File APIs) to create directories and conditionally download files only when missing.
  • Practical implementation notes

    • Store complete tour objects as JSON in SQLite to make offline retrieval straightforward.
    • Use a currentVersion integer and applyMigrations pattern to safely evolve the DB schema for live users.
    • Validate filesystem proactively after upgrades to avoid broken “downloaded” tours.

Actionable takeaways for engineers

  • Treat offline as a first-class requirement: design pipelines that mirror remote layout locally and persist local URIs into durable metadata.
  • Use versioned SQLite migrations to evolve schema safely and to track downloaded content state.
  • Add a version‑check + content validation pass on startup/upgrades to catch iOS file purges and auto‑requeue missing assets.
  • Tune Location.watchPositionAsync (accuracy, timeInterval, distanceInterval) for your use case to balance battery vs precision.
  • Keep downloads idempotent (skip existing files) and perform orchestration in deterministic steps to avoid partial states.

Full Translation

Translations

A translation section that keeps the flow of the original article.

openaijamodel: gpt-5-mini-2025-08-07

Expoで作られたオフラインファーストの多言語オーディオツアーアプリ

Users • React Native • Development • 2026-01-06 • 11分読み物

Clinton Forster(ゲスト著者)

KuratourがどのようにExpoとexpo-audioを使い、オフラインファーストのアーキテクチャでGPSトリガーされたオーディオツアーとツアーオペレーター向けのホワイトラベルアプリを実現しているかを紹介します。Kuratourは、オーストラリア発のフルスタック開発者Clinton Forsterによるアプリで、2025年のAdventure Tourism Awardsで2025 Innovation Awardを受賞しました。

イントロダクション

旅は発見の連続であるべきで、手間やローミング料金、通信状況に邪魔されるべきではありません。多くの旅行者は高いローミング費用や不安定な受信、厳格なツアースケジュールに縛られています。Kuratourはこれを変えるため、スマートフォンを個人用の位置認識型ガイドに変え、世界のどこでも動作するよう設計されています(電波の届かない場所でも動作します)。

Kuratourのビジョン

KuratourはExpoで完全に構築された多言語対応のGPS駆動オーディオツアーアプリです。リアルタイムの位置トリガー、オフライン地図、AI生成ルートにより、徒歩やドライブの没入型体験を提供します。現在は自社プラットフォームだけでなく、オーストラリアをはじめとしたツアーオペレーター向けのホワイトラベルアプリ群にも採用されています。

この記事では、Expo SDKをどのように活用して「オフラインファースト」の課題を解決したか、そして新しいexpo-audioライブラリで現代的なオーディオエンジンをどのように構築したかを解説します。

Expoの基盤:大規模なモダンReact Native

Kuratourは新しいアーキテクチャ上のExpo SDKで完全に構築されており、ファーストパーティモジュールとコミュニティパッケージを組み合わせてネイティブ品質の体験を提供しています。

  • コアモジュール
    • expo-location:リアルタイムGPSトラッキングと領域ベースのトリガー
    • expo-file-systemexpo-sqlite:オフラインデータキャッシュとメディアストレージ
    • expo-audio:スムーズな多言語再生
    • expo-video:導入用の多言語説明チュートリアル
    • expo-splash-screen:起動時の見栄えの良い体験
    • expo-apple-authentication:iOSでのシームレスログイン
    • expo-application:アプリバージョンの確認(オフラインコンテンツの整合性チェックのため)
    • @rnmapbox/maps:対話的でオフライン対応の地図表示

オフラインファースト体験の構築

Kuratourにとって「オフラインファースト」は単なる機能ではなく、コア要件です。旅行者は遠隔地で受信を失ったり、ローミング費用を避けるためにデータ通信を切ることが多いため、次の対策を講じています。

  • 地図タイル、画像、オーディオは事前にダウンロードしておく(expo-file-systemを利用)
  • メタデータや訪問履歴はローカルに保存する(expo-sqliteを利用)
  • 接続状態を検知してオンライン/オフラインを自動切替する
  • expo-locationによるリアルタイムGPSトリガーで、ナレーションを正確なタイミングで再生する

ステップ1:SQLiteで構造化データを管理する

expo-sqliteを用いて、ダウンロード済みツアー、ユーザーの進捗、ローカライズ設定を追跡します。マイグレーションに対応するためにスキーマバージョンを管理しています(例:currentVersion = 3)。主な役割は次のとおりです。

  • データベースを開く(例:openDatabaseSync("db")
  • スキーマバージョンをチェックして必要なマイグレーションを適用
  • ツアーオブジェクトをJSON文字列として保存するためのsetOfflineData(tourID, offlineData)を提供

ステップ2:アセットダウンロードのオーケストレーション

ユーザーが「Download」をタップしたとき、Mapboxタイル、MP3、高解像度画像など複数リソースを同期する必要があります。expo-file-systemを使ってリモートのディレクトリ構造をローカルにミラーリングします。実装のポイントは:

  • CDN上のURLをキーから決定する
  • ドキュメントディレクトリ配下にサブディレクトリを作成して保存する(ユーザーの許可を都度取得せずに保管可能)
  • ローカルに存在しないファイルのみをダウンロードする(File.downloadFileAsync相当)
  • ローカルURIを<Audio><Image> コンポーネントに渡せるように保存する

ステップ3:UIとの統合

TourDownloadコンポーネント内では、プロセスを順次実行します。最初に地図ルートを取得し、次にメイン画像をダウンロードし、最後にツアー内の各ロケーションについて音声と背景トラックを取得します。完了後、ローカルファイルURIをSQLiteに保存して、ネットワーク接続がなくてもアプリが動作するようにします。

ステップ4:カスタムフックでのスマートな切替

ローカル保存が完了したら、どのソースを優先するかをアプリが判断する必要があります。useOfflineDetectorというカスタムフックを作り、useFocusEffect(React Navigation)を利用して、ユーザーがツアーページに遷移するたびにSQLiteを先にチェックするようにしています。主な挙動は次のとおりです。

  • getDatabaseService()でDBインスタンスを取得
  • getOfflineData(tourID)の結果が存在すればオフライン利用可能と判断
  • スクリーンがフォーカスされるたびにチェックを再実行

iOSアップデート時のデータ整合性の扱い

iOSでオフラインファーストアプリを作る際のよくある落とし穴は、アプリのアップデート時にDocumentsディレクトリ内のファイルパスが変わったり、ファイルが意図せず削除/孤立する挙動です。SQLiteは通常持ちこたえますが、expo-file-systemで保存したファイルが見つからないと、ユーザーは「ダウンロード済み」ツアーを開いたときに音声が欠落していることに気付きます。これを防ぐために、KuratourではContent Validation Bridgeを実装しています。

ステップ1:アップデートの検知

expo-applicationを使い、現在実行中のアプリバージョン(Application.nativeApplicationVersion)と、ローカルストレージに保存したlastCheckedVersionを比較します。差異がある場合はバリデーションをトリガーします。

ステップ2:ファイルシステムの検証

recheckDownloadedContentは、SQLiteでオフラインフラグの付いた全ツアーを巡回し、ファイルシステム上に資産が実際に存在するか確認します。メイン画像や最初のオーディオストップが1つでも欠けていれば、バックグラウンドで再ダウンロードを行います。

  • expo-file-systemのファイル存在チェックを行う
  • 不足があれば自動的に再ダウンロードをキューに入れる

発見を促進するためのexpo-location活用

Kuratourの魔法は「ハンズフリー」モードにあります。旅行者がポケットにスマホを入れたまま、自動的に座標に基づいてストーリーが再生されるようにしたい。これを実現するために、権限管理と高精度バックグラウンド購読を扱うカスタムフックuseLocationを作りました。

位置監視の実装ポイント:

  • Location.watchPositionAsyncで数秒ごと、あるいは1メートルの移動ごとに更新を受け取る
  • accuracy: Location.Accuracy.HightimeIntervaldistanceIntervalを調整してウォーキングツアーの精度を確保
  • フォアグラウンドパーミッションを要求し、許可がなければ購読を開始しない

expo-audioでのレイヤードサウンドのオーケストレーション

Kuratourの体験は単にテキストを読むことではなく、雰囲気を作ることにあります。ナレーション、背景アンビエンス、効果音を重ね合わせ、音量やパンをリアルタイムで制御し、シームレスなクロスフェードを行うためにexpo-audioを利用しています。音声はローカルURIを取得して各オーディオトラックを個別に扱い、以下のような制御を行います:

  • ナレーショントラックと背景トラックの独立した再生/停止/フェード
  • 場所や方角に応じたパンや音量の調整(定位効果)
  • 言語や声の切替(多言語対応)をシームレスに行うためのプリロード

まとめ

KuratourはExpo SDKの力を引き出し、厳しいオフライン要件とロケーション駆動の体験を両立させたアプリです。expo-sqliteでのローカルデータ管理、expo-file-systemによる事前ダウンロード、expo-locationの高精度トラッキング、そしてexpo-audioによる層状オーディオ処理を組み合わせることで、世界中のどこでも動作するハンズフリーの多言語オーディオツアーが実現できました。