# mahlernim/google-timeline-visualizer architecture

> Architecture diagram of the GitHub repository mahlernim/google-timeline-visualizer, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-26). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/mahlernim/google-timeline-visualizer
- Repository: https://github.com/mahlernim/google-timeline-visualizer

## Overview

Timeline Visualizer turns an exported Google Timeline file into a configurable animated travel video, on Android and in a private iPhone web app. The main Android workflow imports route history into a local Travel Journal, selects a trip or date range, previews the map, then exports and catalogs an MP4. The graph also preserves documented trip recaps, presets, settings, reminders, and video-library actions. Sampled code confirms route projection, tile caching, export-service, and web entry-point behavior; other connections follow README capabilities and are shown conservatively.

Main entry points: [`app/src/main/java/dev/mahlernim/timelinevisualizer/MainActivity.kt`](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/MainActivity.kt) (Android app), [`web/src/main.ts`](https://github.com/mahlernim/google-timeline-visualizer/blob/main/web/src/main.ts) (iPhone web app), [`app/src/main/java/dev/mahlernim/timelinevisualizer/journal/JournalRepository.kt`](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/journal/JournalRepository.kt) (Journal repository), [`app/src/main/java/dev/mahlernim/timelinevisualizer/export/VideoExportService.kt`](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/export/VideoExportService.kt) (Export service)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_experience["App experience"]
  node_main_activity["Android app<br/>[MainActivity.kt]"]
  node_web_app["iPhone web app<br/>[main.ts]"]
  node_settings["Video settings"]
end

subgraph group_timeline["Timeline and journal"]
  node_timeline_parser["Timeline parser<br/>[TimelineParser.kt]"]
  node_signal_processor["Signal processing"]
  node_journal_import["Journal import"]
  node_journal_repo["Journal repository"]
  node_journal_db[("Journal database<br/>[JournalDatabase.kt]")]
  node_route_service["Route projection"]
  node_web_import["Web import<br/>[import-client.ts]"]
end

subgraph group_journey["Journey design"]
  node_trip_detection["Trip detection<br/>[TripDetector.kt]"]
  node_trip_store[("Trip store<br/>[TripsStore.kt]")]
  node_presets["Video presets"]
end

subgraph group_rendering["Preview and export"]
  node_timeline_render["Journey animation"]
  node_painter["Map painter<br/>[TimelinePainter.kt]"]
  node_tile_repository[("Map tile cache<br/>[TileRepository.kt]")]
  node_export_service["Export service"]
  node_mp4_exporter["MP4 encoder<br/>[Mp4Exporter.kt]"]
  node_web_renderer["Web renderer<br/>[renderer.ts]"]
  node_web_video["Web video export<br/>[video.ts]"]
  node_web_tiles[("Web tile cache<br/>[tile-cache.ts]")]
end

subgraph group_library["Videos and integrations"]
  node_video_library["Video library"]
  node_generated_media[("Generated media index")]
  node_reminders["Journal reminders"]
end

node_traveler(("Traveler"))
node_timeline_file["Timeline JSON"]
node_map_tiles["Map tile service"]
node_media_store[("Android media storage")]

node_traveler -->|"uses"| node_main_activity
node_timeline_file -->|"selects"| node_main_activity
node_main_activity -->|"imports"| node_timeline_parser
node_timeline_parser -->|"processes"| node_signal_processor
node_main_activity -->|"imports into"| node_journal_import
node_journal_import -->|"adapts data"| node_journal_repo
node_journal_repo -->|"persists"| node_journal_db
node_main_activity -->|"reads journal"| node_journal_repo
node_main_activity -->|"requests route"| node_route_service
node_route_service -->|"reads observations"| node_journal_repo
node_main_activity -->|"finds trips"| node_trip_detection
node_trip_detection -->|"stores trips"| node_trip_store
node_main_activity -->|"manages presets"| node_presets
node_main_activity -->|"configures"| node_settings
node_main_activity -->|"previews journey"| node_timeline_render
node_timeline_render -->|"draws frames"| node_painter
node_painter -->|"loads tiles"| node_tile_repository
node_tile_repository -->|"fetches tiles"| node_map_tiles
node_main_activity -->|"starts export"| node_export_service
node_export_service -->|"encodes video"| node_mp4_exporter
node_mp4_exporter -->|"renders frames"| node_painter
node_export_service -->|"saves MP4"| node_media_store
node_main_activity -->|"browses videos"| node_video_library
node_video_library -->|"reads index"| node_generated_media
node_video_library -->|"plays or manages"| node_media_store
node_main_activity -->|"coordinates"| node_reminders
node_traveler -.->|"uses"| node_web_app
node_web_app -->|"imports file"| node_web_import
node_timeline_file -.->|"selects privately"| node_web_app
node_web_app -->|"previews journey"| node_web_renderer
node_web_renderer -->|"loads tiles"| node_web_tiles
node_web_tiles -.->|"fetches tiles"| node_map_tiles
node_web_app -->|"creates MP4"| node_web_video
node_web_video -->|"shares or downloads"| node_traveler

click node_main_activity "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/MainActivity.kt"
click node_web_app "https://github.com/mahlernim/google-timeline-visualizer/blob/main/web/src/main.ts"
click node_settings "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/ui/SettingsViewModel.kt"
click node_timeline_parser "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/data/TimelineParser.kt"
click node_signal_processor "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/data/RawSignalProcessor.kt"
click node_journal_import "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/journal/importer/TimelineJournalImportAdapter.kt"
click node_journal_repo "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/journal/JournalRepository.kt"
click node_journal_db "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/journal/JournalDatabase.kt"
click node_route_service "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/journal/route/JournalRouteService.kt"
click node_trip_detection "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/trips/TripDetector.kt"
click node_trip_store "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/trips/TripsStore.kt"
click node_presets "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/presets/PresetRepository.kt"
click node_timeline_render "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/render/TimelineAnimation.kt"
click node_painter "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/render/TimelinePainter.kt"
click node_tile_repository "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/data/TileRepository.kt"
click node_export_service "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/export/VideoExportService.kt"
click node_mp4_exporter "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/export/Mp4Exporter.kt"
click node_video_library "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/videos/VideoLibraryViewModel.kt"
click node_generated_media "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/videos/GeneratedMediaRepository.kt"
click node_reminders "https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/journal/reminder/JournalReminderCoordinator.kt"
click node_web_import "https://github.com/mahlernim/google-timeline-visualizer/blob/main/web/src/import-client.ts"
click node_web_renderer "https://github.com/mahlernim/google-timeline-visualizer/blob/main/web/src/renderer.ts"
click node_web_video "https://github.com/mahlernim/google-timeline-visualizer/blob/main/web/src/video.ts"
click node_web_tiles "https://github.com/mahlernim/google-timeline-visualizer/blob/main/web/src/tile-cache.ts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_main_activity,node_web_app,node_settings toneBlue
class node_timeline_parser,node_signal_processor,node_journal_import,node_journal_repo,node_journal_db,node_route_service,node_web_import,node_media_store toneAmber
class node_trip_detection,node_trip_store,node_presets toneMint
class node_timeline_render,node_painter,node_tile_repository,node_export_service,node_mp4_exporter,node_web_renderer,node_web_video,node_web_tiles toneRose
class node_video_library,node_generated_media,node_reminders,node_traveler,node_timeline_file,node_map_tiles toneIndigo
```

## Components

### App experience

- [Android app](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/MainActivity.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/MainActivity.kt`
- [iPhone web app](https://github.com/mahlernim/google-timeline-visualizer/blob/main/web/src/main.ts): `web/src/main.ts`
- [Video settings](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/ui/SettingsViewModel.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/ui/SettingsViewModel.kt`

### Timeline and journal

- [Timeline parser](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/data/TimelineParser.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/data/TimelineParser.kt`
- [Signal processing](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/data/RawSignalProcessor.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/data/RawSignalProcessor.kt`
- [Journal import](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/journal/importer/TimelineJournalImportAdapter.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/journal/importer/TimelineJournalImportAdapter.kt`
- [Journal repository](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/journal/JournalRepository.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/journal/JournalRepository.kt`
- [Journal database](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/journal/JournalDatabase.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/journal/JournalDatabase.kt`
- [Route projection](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/journal/route/JournalRouteService.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/journal/route/JournalRouteService.kt`
- [Web import](https://github.com/mahlernim/google-timeline-visualizer/blob/main/web/src/import-client.ts): `web/src/import-client.ts`

### Journey design

- [Trip detection](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/trips/TripDetector.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/trips/TripDetector.kt`
- [Trip store](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/trips/TripsStore.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/trips/TripsStore.kt`
- [Video presets](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/presets/PresetRepository.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/presets/PresetRepository.kt`

### Preview and export

- [Journey animation](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/render/TimelineAnimation.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/render/TimelineAnimation.kt`
- [Map painter](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/render/TimelinePainter.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/render/TimelinePainter.kt`
- [Map tile cache](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/data/TileRepository.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/data/TileRepository.kt`
- [Export service](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/export/VideoExportService.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/export/VideoExportService.kt`
- [MP4 encoder](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/export/Mp4Exporter.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/export/Mp4Exporter.kt`
- [Web renderer](https://github.com/mahlernim/google-timeline-visualizer/blob/main/web/src/renderer.ts): `web/src/renderer.ts`
- [Web video export](https://github.com/mahlernim/google-timeline-visualizer/blob/main/web/src/video.ts): `web/src/video.ts`
- [Web tile cache](https://github.com/mahlernim/google-timeline-visualizer/blob/main/web/src/tile-cache.ts): `web/src/tile-cache.ts`

### Videos and integrations

- [Video library](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/videos/VideoLibraryViewModel.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/videos/VideoLibraryViewModel.kt`
- [Generated media index](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/videos/GeneratedMediaRepository.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/videos/GeneratedMediaRepository.kt`
- [Journal reminders](https://github.com/mahlernim/google-timeline-visualizer/blob/main/app/src/main/java/dev/mahlernim/timelinevisualizer/journal/reminder/JournalReminderCoordinator.kt): `app/src/main/java/dev/mahlernim/timelinevisualizer/journal/reminder/JournalReminderCoordinator.kt`

### Other components

- **Traveler**
- **Timeline JSON**
- **Map tile service**
- **Android media storage**

## Connections

- Traveler → Android app: uses
- Timeline JSON → Android app: selects
- Android app → Timeline parser: imports
- Timeline parser → Signal processing: processes
- Android app → Journal import: imports into
- Journal import → Journal repository: adapts data
- Journal repository → Journal database: persists
- Android app → Journal repository: reads journal
- Android app → Route projection: requests route
- Route projection → Journal repository: reads observations
- Android app → Trip detection: finds trips
- Trip detection → Trip store: stores trips
- Android app → Video presets: manages presets
- Android app → Video settings: configures
- Android app → Journey animation: previews journey
- Journey animation → Map painter: draws frames
- Map painter → Map tile cache: loads tiles
- Map tile cache → Map tile service: fetches tiles
- Android app → Export service: starts export
- Export service → MP4 encoder: encodes video
- MP4 encoder → Map painter: renders frames
- Export service → Android media storage: saves MP4
- Android app → Video library: browses videos
- Video library → Generated media index: reads index
- Video library → Android media storage: plays or manages
- Android app → Journal reminders: coordinates
- Traveler → iPhone web app: uses
- iPhone web app → Web import: imports file
- Timeline JSON → iPhone web app: selects privately
- iPhone web app → Web renderer: previews journey
- Web renderer → Web tile cache: loads tiles
- Web tile cache → Map tile service: fetches tiles
- iPhone web app → Web video export: creates MP4
- Web video export → Traveler: shares or downloads
