# teerin27/long-run architecture

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

- Interactive diagram: https://gitdiagram.com/teerin27/long-run
- Repository: https://github.com/teerin27/long-run

## Overview

Long-run is a mobile running tracker with a NestJS API. The user signs in through Firebase, records a GPS run, submits its track for server-side PostGIS distance calculation and storage, then views run history and distance rankings. The graph separates mobile flows, API domain services and persistence/integrations. Edges follow shown calls or explicit README descriptions; some screen and service internals were not excerpted, so documented connections are used where applicable and uncertain ones are omitted. Notifications are planned and have no implementation path in this tree.

Main entry points: [`apps/mobile/src/services/api.ts`](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/services/api.ts) (API client), [`apps/mobile/src/store/AuthContext.tsx`](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/store/AuthContext.tsx) (Auth context), [`apps/mobile/src/navigation/MainStack.tsx`](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/navigation/MainStack.tsx) (Main navigation), [`apps/mobile/src/navigation/RootNavigator.tsx`](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/navigation/RootNavigator.tsx) (Auth routing)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_mobile["Mobile app"]
  node_root["App entry<br/>[App.tsx]"]
  node_authnav["Auth navigation<br/>[AuthStack.tsx]"]
  node_mainnav["Main navigation<br/>[MainStack.tsx]"]
  node_rootnav["Auth routing<br/>[RootNavigator.tsx]"]
  node_authstate["Auth context<br/>[AuthContext.tsx]"]
  node_authscreens["Sign-in screens<br/>[SignInScreen.tsx]"]
  node_signup["Sign-up screen<br/>[SignUpScreen.tsx]"]
  node_apiclient["API client<br/>[api.ts]"]
end

subgraph group_identity["Identity and profiles"]
  node_authservice["Firebase auth client<br/>[authService.ts]"]
  node_firebaseclient["Firebase client<br/>[firebase.ts]"]
  node_authapi["Auth endpoints<br/>[auth.controller.ts]"]
  node_authserviceapi["Profile sync<br/>[auth.service.ts]"]
  node_authguard["Token guard"]
  node_users["User profiles<br/>[users.service.ts]"]
  node_usersdb[("PostgreSQL profiles<br/>[user.entity.ts]")]
end

subgraph group_running["Run activities"]
  node_record["Run recording"]
  node_location["GPS tracking<br/>[locationService.ts]"]
  node_activityclient["Activity API client"]
  node_history["Run history screen"]
  node_activitycontroller["Activity endpoints"]
  node_activityservice["Activity processing"]
  node_activitydb[("PostGIS activities<br/>[activity.entity.ts]")]
end

subgraph group_rankings["Leaderboards"]
  node_leaderboardwrite["Ranking updates"]
  node_redis[("Redis sorted sets<br/>[redis.provider.ts]")]
  node_leaderboardcontroller["Ranking endpoints"]
  node_leaderboardclient["Ranking API client"]
  node_leaderboardscreen["Leaderboard screen"]
end

node_runner(("Runner"))
node_shared["Shared data types<br/>[activity.ts]"]
node_database[("PostgreSQL + PostGIS")]

node_runner -->|"opens app"| node_root
node_root -->|"provides auth"| node_authstate
node_root -->|"renders"| node_rootnav
node_rootnav -->|"checks session"| node_authstate
node_rootnav -->|"routes signed out"| node_authnav
node_rootnav -->|"routes signed in"| node_mainnav
node_authnav -->|"shows sign in"| node_authscreens
node_authnav -->|"shows sign up"| node_signup
node_mainnav -->|"routes to"| node_record
node_mainnav -->|"routes to"| node_history
node_mainnav -->|"routes to"| node_leaderboardscreen
node_authstate -->|"calls sign-up"| node_authservice
node_authstate -->|"syncs profile"| node_apiclient
node_authservice -->|"uses Firebase"| node_firebaseclient
node_authscreens -.->|"uses auth"| node_authstate
node_signup -->|"uses auth"| node_authstate
node_apiclient -->|"gets token"| node_firebaseclient
node_apiclient -->|"calls API"| node_authapi
node_authapi -->|"guards routes"| node_authguard
node_authapi -->|"syncs profile"| node_authserviceapi
node_authguard -.->|"verifies token"| node_firebaseclient
node_authserviceapi -->|"finds or creates"| node_users
node_users -->|"persists profiles"| node_usersdb
node_record -->|"tracks GPS"| node_location
node_record -->|"submits run"| node_activityclient
node_activityclient -->|"sends request"| node_apiclient
node_apiclient -.->|"calls API"| node_activitycontroller
node_activitycontroller -->|"guards routes"| node_authguard
node_activitycontroller -->|"resolves owner"| node_users
node_activitycontroller -->|"delegates"| node_activityservice
node_activityservice -->|"stores and queries"| node_activitydb
node_activitydb -->|"uses PostGIS"| node_database
node_activityservice -->|"records distance"| node_leaderboardwrite
node_leaderboardwrite -->|"updates rankings"| node_redis
node_history -.->|"loads history"| node_activityclient
node_leaderboardscreen -->|"loads rankings"| node_leaderboardclient
node_leaderboardclient -->|"sends request"| node_apiclient
node_apiclient -.->|"calls API"| node_leaderboardcontroller
node_leaderboardcontroller -->|"guards routes"| node_authguard
node_leaderboardcontroller -->|"reads rankings"| node_leaderboardwrite
node_leaderboardcontroller -->|"gets display names"| node_users
node_leaderboardwrite -.->|"uses activity data"| node_shared

click node_root "https://github.com/teerin27/long-run/blob/main/apps/mobile/App.tsx"
click node_authnav "https://github.com/teerin27/long-run/blob/main/apps/mobile/src/navigation/AuthStack.tsx"
click node_mainnav "https://github.com/teerin27/long-run/blob/main/apps/mobile/src/navigation/MainStack.tsx"
click node_rootnav "https://github.com/teerin27/long-run/blob/main/apps/mobile/src/navigation/RootNavigator.tsx"
click node_authstate "https://github.com/teerin27/long-run/blob/main/apps/mobile/src/store/AuthContext.tsx"
click node_authscreens "https://github.com/teerin27/long-run/blob/main/apps/mobile/src/screens/SignInScreen.tsx"
click node_signup "https://github.com/teerin27/long-run/blob/main/apps/mobile/src/screens/SignUpScreen.tsx"
click node_authservice "https://github.com/teerin27/long-run/blob/main/apps/mobile/src/services/authService.ts"
click node_firebaseclient "https://github.com/teerin27/long-run/blob/main/apps/mobile/src/services/firebase.ts"
click node_apiclient "https://github.com/teerin27/long-run/blob/main/apps/mobile/src/services/api.ts"
click node_authapi "https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/auth/auth.controller.ts"
click node_authserviceapi "https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/auth/auth.service.ts"
click node_authguard "https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/auth/firebase-auth.guard.ts"
click node_users "https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/users/users.service.ts"
click node_usersdb "https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/users/entities/user.entity.ts"
click node_record "https://github.com/teerin27/long-run/blob/main/apps/mobile/src/screens/RecordRunScreen.tsx"
click node_location "https://github.com/teerin27/long-run/blob/main/apps/mobile/src/services/locationService.ts"
click node_activityclient "https://github.com/teerin27/long-run/blob/main/apps/mobile/src/services/activitiesService.ts"
click node_history "https://github.com/teerin27/long-run/blob/main/apps/mobile/src/screens/ActivitiesListScreen.tsx"
click node_activitycontroller "https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/activities/activities.controller.ts"
click node_activityservice "https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/activities/activities.service.ts"
click node_activitydb "https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/activities/entities/activity.entity.ts"
click node_leaderboardwrite "https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/leaderboard/leaderboard.service.ts"
click node_redis "https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/leaderboard/redis.provider.ts"
click node_leaderboardcontroller "https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/leaderboard/leaderboard.controller.ts"
click node_leaderboardclient "https://github.com/teerin27/long-run/blob/main/apps/mobile/src/services/leaderboardService.ts"
click node_leaderboardscreen "https://github.com/teerin27/long-run/blob/main/apps/mobile/src/screens/LeaderboardScreen.tsx"
click node_shared "https://github.com/teerin27/long-run/blob/main/packages/shared/src/types/activity.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_root,node_authnav,node_mainnav,node_rootnav,node_authstate,node_authscreens,node_signup,node_apiclient toneBlue
class node_authservice,node_firebaseclient,node_authapi,node_authserviceapi,node_authguard,node_users,node_usersdb,node_database toneAmber
class node_record,node_location,node_activityclient,node_history,node_activitycontroller,node_activityservice,node_activitydb toneMint
class node_leaderboardwrite,node_redis,node_leaderboardcontroller,node_leaderboardclient,node_leaderboardscreen toneRose
class node_runner toneIndigo
class node_shared toneTeal
```

## Components

### Mobile app

- [App entry](https://github.com/teerin27/long-run/blob/main/apps/mobile/App.tsx): `apps/mobile/App.tsx`
- [Auth navigation](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/navigation/AuthStack.tsx): `apps/mobile/src/navigation/AuthStack.tsx`
- [Main navigation](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/navigation/MainStack.tsx): `apps/mobile/src/navigation/MainStack.tsx`
- [Auth routing](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/navigation/RootNavigator.tsx): `apps/mobile/src/navigation/RootNavigator.tsx`
- [Auth context](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/store/AuthContext.tsx): `apps/mobile/src/store/AuthContext.tsx`
- [Sign-in screens](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/screens/SignInScreen.tsx): `apps/mobile/src/screens/SignInScreen.tsx`
- [Sign-up screen](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/screens/SignUpScreen.tsx): `apps/mobile/src/screens/SignUpScreen.tsx`
- [API client](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/services/api.ts): `apps/mobile/src/services/api.ts`

### Identity and profiles

- [Firebase auth client](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/services/authService.ts): `apps/mobile/src/services/authService.ts`
- [Firebase client](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/services/firebase.ts): `apps/mobile/src/services/firebase.ts`
- [Auth endpoints](https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/auth/auth.controller.ts): `apps/api/src/modules/auth/auth.controller.ts`
- [Profile sync](https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/auth/auth.service.ts): `apps/api/src/modules/auth/auth.service.ts`
- [Token guard](https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/auth/firebase-auth.guard.ts): `apps/api/src/modules/auth/firebase-auth.guard.ts`
- [User profiles](https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/users/users.service.ts): `apps/api/src/modules/users/users.service.ts`
- [PostgreSQL profiles](https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/users/entities/user.entity.ts): `apps/api/src/modules/users/entities/user.entity.ts`

### Run activities

- [Run recording](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/screens/RecordRunScreen.tsx): `apps/mobile/src/screens/RecordRunScreen.tsx`
- [GPS tracking](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/services/locationService.ts): `apps/mobile/src/services/locationService.ts`
- [Activity API client](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/services/activitiesService.ts): `apps/mobile/src/services/activitiesService.ts`
- [Run history screen](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/screens/ActivitiesListScreen.tsx): `apps/mobile/src/screens/ActivitiesListScreen.tsx`
- [Activity endpoints](https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/activities/activities.controller.ts): `apps/api/src/modules/activities/activities.controller.ts`
- [Activity processing](https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/activities/activities.service.ts): `apps/api/src/modules/activities/activities.service.ts`
- [PostGIS activities](https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/activities/entities/activity.entity.ts): `apps/api/src/modules/activities/entities/activity.entity.ts`

### Leaderboards

- [Ranking updates](https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/leaderboard/leaderboard.service.ts): `apps/api/src/modules/leaderboard/leaderboard.service.ts`
- [Redis sorted sets](https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/leaderboard/redis.provider.ts): `apps/api/src/modules/leaderboard/redis.provider.ts`
- [Ranking endpoints](https://github.com/teerin27/long-run/blob/main/apps/api/src/modules/leaderboard/leaderboard.controller.ts): `apps/api/src/modules/leaderboard/leaderboard.controller.ts`
- [Ranking API client](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/services/leaderboardService.ts): `apps/mobile/src/services/leaderboardService.ts`
- [Leaderboard screen](https://github.com/teerin27/long-run/blob/main/apps/mobile/src/screens/LeaderboardScreen.tsx): `apps/mobile/src/screens/LeaderboardScreen.tsx`

### Other components

- **Runner**
- [Shared data types](https://github.com/teerin27/long-run/blob/main/packages/shared/src/types/activity.ts): `packages/shared/src/types/activity.ts`
- **PostgreSQL + PostGIS**

## Connections

- Runner → App entry: opens app (evidence: `apps/mobile/App.tsx`)
- App entry → Auth context: provides auth (evidence: `apps/mobile/App.tsx`)
- App entry → Auth routing: renders (evidence: `apps/mobile/App.tsx`)
- Auth routing → Auth context: checks session (evidence: `apps/mobile/src/navigation/RootNavigator.tsx`)
- Auth routing → Auth navigation: routes signed out (evidence: `apps/mobile/src/navigation/RootNavigator.tsx`)
- Auth routing → Main navigation: routes signed in (evidence: `apps/mobile/src/navigation/RootNavigator.tsx`)
- Auth navigation → Sign-in screens: shows sign in (evidence: `apps/mobile/src/navigation/AuthStack.tsx`)
- Auth navigation → Sign-up screen: shows sign up (evidence: `apps/mobile/src/navigation/AuthStack.tsx`)
- Main navigation → Run recording: routes to (evidence: `apps/mobile/src/navigation/MainStack.tsx`)
- Main navigation → Run history screen: routes to (evidence: `apps/mobile/src/navigation/MainStack.tsx`)
- Main navigation → Leaderboard screen: routes to (evidence: `apps/mobile/src/navigation/MainStack.tsx`)
- Auth context → Firebase auth client: calls sign-up (evidence: `apps/mobile/src/store/AuthContext.tsx`)
- Auth context → API client: syncs profile (evidence: `apps/mobile/src/store/AuthContext.tsx`)
- Firebase auth client → Firebase client: uses Firebase (evidence: `apps/mobile/src/services/authService.ts`)
- Sign-in screens → Auth context: uses auth (evidence: `apps/mobile/src/store/AuthContext.tsx`)
- Sign-up screen → Auth context: uses auth (evidence: `apps/mobile/src/screens/SignUpScreen.tsx`)
- API client → Firebase client: gets token (evidence: `apps/mobile/src/services/api.ts`)
- API client → Auth endpoints: calls API
- Auth endpoints → Token guard: guards routes (evidence: `apps/api/src/modules/auth/auth.controller.ts`)
- Auth endpoints → Profile sync: syncs profile (evidence: `apps/api/src/modules/auth/auth.controller.ts`)
- Token guard → Firebase client: verifies token
- Profile sync → User profiles: finds or creates (evidence: `apps/api/src/modules/auth/auth.service.ts`)
- User profiles → PostgreSQL profiles: persists profiles (evidence: `apps/api/src/modules/users/users.service.ts`)
- Run recording → GPS tracking: tracks GPS (evidence: `apps/mobile/src/screens/RecordRunScreen.tsx`)
- Run recording → Activity API client: submits run (evidence: `apps/mobile/src/screens/RecordRunScreen.tsx`)
- Activity API client → API client: sends request (evidence: `apps/mobile/src/services/activitiesService.ts`)
- API client → Activity endpoints: calls API (evidence: `README.md`)
- Activity endpoints → Token guard: guards routes (evidence: `apps/api/src/modules/activities/activities.controller.ts`)
- Activity endpoints → User profiles: resolves owner (evidence: `apps/api/src/modules/activities/activities.controller.ts`)
- Activity endpoints → Activity processing: delegates (evidence: `apps/api/src/modules/activities/activities.controller.ts`)
- Activity processing → PostGIS activities: stores and queries (evidence: `apps/api/src/modules/activities/activities.service.ts`)
- PostGIS activities → PostgreSQL + PostGIS: uses PostGIS
- Activity processing → Ranking updates: records distance (evidence: `apps/api/src/modules/activities/activities.service.ts`)
- Ranking updates → Redis sorted sets: updates rankings (evidence: `apps/api/src/modules/leaderboard/leaderboard.service.ts`)
- Run history screen → Activity API client: loads history (evidence: `README.md`)
- Leaderboard screen → Ranking API client: loads rankings (evidence: `apps/mobile/src/screens/LeaderboardScreen.tsx`)
- Ranking API client → API client: sends request (evidence: `apps/mobile/src/services/leaderboardService.ts`)
- API client → Ranking endpoints: calls API (evidence: `README.md`)
- Ranking endpoints → Token guard: guards routes (evidence: `apps/api/src/modules/leaderboard/leaderboard.controller.ts`)
- Ranking endpoints → Ranking updates: reads rankings (evidence: `apps/api/src/modules/leaderboard/leaderboard.controller.ts`)
- Ranking endpoints → User profiles: gets display names (evidence: `apps/api/src/modules/leaderboard/leaderboard.controller.ts`)
- Ranking updates → Shared data types: uses activity data
