# developeracademy-postech/2026-c6-m02-urchin-ios architecture

> Architecture diagram of the GitHub repository developeracademy-postech/2026-c6-m02-urchin-ios, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-09). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/developeracademy-postech/2026-c6-m02-urchin-ios
- Repository: https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios

## Overview

Plobby is an iOS beach-cleanup activity app: volunteers can record cleanup activity and photos, explore beaches and community records, track collection goals, and manage profiles and notifications. The principal workflow is recording an activity, including its location, time, trash and photos, then saving it through the record client to Supabase; the app also exposes map, collection, account and notification branches. The README documents the feature/domain/client layering. Several feature-to-client calls and unsampled implementations are not shown, so those relationships are omitted rather than asserted.

Main entry points: [`Plobby/Plobby/Clients/Supabase/SupabaseClient+.swift`](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Supabase/SupabaseClient%2B.swift) (Supabase backend), [`Plobby/Plobby/Features/MainTab/MainTabFeature.swift`](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/MainTab/MainTabFeature.swift) (Main tabs), [`Plobby/Plobby/Features/Record/RecordFlowFeature.swift`](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Record/RecordFlowFeature.swift) (Record flow), [`Plobby/Plobby/Clients/Record/RecordClient.swift`](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Record/RecordClient.swift) (Record service)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_app["App shell"]
  node_app_root["App routing<br/>[AppFeature.swift]"]
  node_tabs["Main tabs"]
  node_home["Home<br/>[HomeFeature.swift]"]
end

subgraph group_activity["Cleanup activity"]
  node_record_flow["Record flow"]
  node_record_form["Record form"]
  node_photo_picker["Photo picker"]
  node_record_detail["Record detail"]
  node_record_client["Record service<br/>[RecordClient.swift]"]
  node_record_domain["Record models<br/>[NewRecord.swift]"]
end

subgraph group_discovery["Beach discovery"]
  node_map["Beach map<br/>[MapFeature.swift]"]
  node_beach_client["Beach service<br/>[BeachClient.swift]"]
  node_beach_domain["Beach models<br/>[Beach.swift]"]
  node_collection["Goal collection"]
  node_goal_client["Goal service<br/>[GoalClient.swift]"]
end

subgraph group_account["Member services"]
  node_onboarding["Onboarding"]
  node_signup["Sign-up"]
  node_auth_client["Authentication<br/>[AuthClient.swift]"]
  node_user_client["Profile service<br/>[UserClient.swift]"]
  node_notification_client["Notifications"]
end

subgraph group_platform["Platform clients"]
  node_photo_client["Photo library"]
  node_location_client["Location"]
  node_push_client["Push<br/>[PushClient.swift]"]
  node_supabase[("Supabase backend")]
end

node_volunteer(("Volunteer"))

node_volunteer -->|"uses app"| node_app_root
node_app_root -->|"routes tabs"| node_tabs
node_tabs -.->|"offers home"| node_home
node_tabs -.->|"offers map"| node_map
node_tabs -.->|"offers goals"| node_collection
node_volunteer -.->|"records cleanup"| node_record_flow
node_record_flow -.->|"presents form"| node_record_form
node_record_form -.->|"collects details"| node_record_domain
node_record_flow -.->|"selects photos"| node_photo_picker
node_photo_picker -->|"loads library"| node_photo_client
node_record_detail -.->|"loads record"| node_record_client
node_record_client -->|"reads writes"| node_supabase
node_record_client -->|"maps records"| node_record_domain
node_map -.->|"loads beaches"| node_beach_client
node_beach_client -->|"queries beaches"| node_supabase
node_beach_client -->|"maps beaches"| node_beach_domain
node_collection -.->|"loads progress"| node_goal_client
node_goal_client -->|"reads goals"| node_supabase
node_onboarding -.->|"authenticates"| node_auth_client
node_signup -.->|"updates profile"| node_user_client
node_notification_client -->|"reads updates"| node_supabase
node_auth_client -->|"auth requests"| node_supabase
node_user_client -->|"profile requests"| node_supabase
node_location_client -->|"provides location"| node_volunteer
node_push_client -.->|"delivers alerts"| node_volunteer

click node_app_root "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/App/AppFeature.swift"
click node_tabs "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/MainTab/MainTabFeature.swift"
click node_home "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Home/HomeFeature.swift"
click node_onboarding "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Onboarding/OnboardingFeature.swift"
click node_signup "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/SignUp/SignUpFeature.swift"
click node_record_flow "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Record/RecordFlowFeature.swift"
click node_record_form "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Record/RecordForm/RecordFormFeature.swift"
click node_photo_picker "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Record/PhotosPicker/PhotosPickerFeature.swift"
click node_record_detail "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Record/RecordDetail/RecordDetailFeature.swift"
click node_record_client "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Record/RecordClient.swift"
click node_record_domain "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Domain/Record/NewRecord.swift"
click node_map "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Map/MapFeature.swift"
click node_beach_client "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Beach/BeachClient.swift"
click node_beach_domain "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Domain/Beach/Beach.swift"
click node_collection "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Collection/CollectionFeature.swift"
click node_goal_client "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Goal/GoalClient.swift"
click node_auth_client "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Auth/AuthClient.swift"
click node_user_client "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/User/UserClient.swift"
click node_notification_client "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Notification/NotificationClient.swift"
click node_photo_client "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Photo/PhotoLibraryClient.swift"
click node_location_client "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Location/LocationClient.swift"
click node_push_client "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Push/PushClient.swift"
click node_supabase "https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Supabase/SupabaseClient%2B.swift"

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_app_root,node_tabs,node_home toneBlue
class node_record_flow,node_record_form,node_photo_picker,node_record_detail,node_record_client,node_record_domain toneAmber
class node_map,node_beach_client,node_beach_domain,node_collection,node_goal_client toneMint
class node_onboarding,node_signup,node_auth_client,node_user_client,node_notification_client toneRose
class node_photo_client,node_location_client,node_push_client,node_supabase,node_volunteer toneIndigo
```

## Components

### App shell

- [App routing](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/App/AppFeature.swift): `Plobby/Plobby/App/AppFeature.swift`
- [Main tabs](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/MainTab/MainTabFeature.swift): `Plobby/Plobby/Features/MainTab/MainTabFeature.swift`
- [Home](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Home/HomeFeature.swift): `Plobby/Plobby/Features/Home/HomeFeature.swift`

### Cleanup activity

- [Record flow](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Record/RecordFlowFeature.swift): `Plobby/Plobby/Features/Record/RecordFlowFeature.swift`
- [Record form](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Record/RecordForm/RecordFormFeature.swift): `Plobby/Plobby/Features/Record/RecordForm/RecordFormFeature.swift`
- [Photo picker](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Record/PhotosPicker/PhotosPickerFeature.swift): `Plobby/Plobby/Features/Record/PhotosPicker/PhotosPickerFeature.swift`
- [Record detail](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Record/RecordDetail/RecordDetailFeature.swift): `Plobby/Plobby/Features/Record/RecordDetail/RecordDetailFeature.swift`
- [Record service](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Record/RecordClient.swift): `Plobby/Plobby/Clients/Record/RecordClient.swift`
- [Record models](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Domain/Record/NewRecord.swift): `Plobby/Plobby/Domain/Record/NewRecord.swift`

### Beach discovery

- [Beach map](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Map/MapFeature.swift): `Plobby/Plobby/Features/Map/MapFeature.swift`
- [Beach service](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Beach/BeachClient.swift): `Plobby/Plobby/Clients/Beach/BeachClient.swift`
- [Beach models](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Domain/Beach/Beach.swift): `Plobby/Plobby/Domain/Beach/Beach.swift`
- [Goal collection](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Collection/CollectionFeature.swift): `Plobby/Plobby/Features/Collection/CollectionFeature.swift`
- [Goal service](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Goal/GoalClient.swift): `Plobby/Plobby/Clients/Goal/GoalClient.swift`

### Member services

- [Onboarding](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/Onboarding/OnboardingFeature.swift): `Plobby/Plobby/Features/Onboarding/OnboardingFeature.swift`
- [Sign-up](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Features/SignUp/SignUpFeature.swift): `Plobby/Plobby/Features/SignUp/SignUpFeature.swift`
- [Authentication](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Auth/AuthClient.swift): `Plobby/Plobby/Clients/Auth/AuthClient.swift`
- [Profile service](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/User/UserClient.swift): `Plobby/Plobby/Clients/User/UserClient.swift`
- [Notifications](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Notification/NotificationClient.swift): `Plobby/Plobby/Clients/Notification/NotificationClient.swift`

### Platform clients

- [Photo library](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Photo/PhotoLibraryClient.swift): `Plobby/Plobby/Clients/Photo/PhotoLibraryClient.swift`
- [Location](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Location/LocationClient.swift): `Plobby/Plobby/Clients/Location/LocationClient.swift`
- [Push](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Push/PushClient.swift): `Plobby/Plobby/Clients/Push/PushClient.swift`
- [Supabase backend](https://github.com/developeracademy-postech/2026-c6-m02-urchin-ios/blob/develop/Plobby/Plobby/Clients/Supabase/SupabaseClient%2B.swift): `Plobby/Plobby/Clients/Supabase/SupabaseClient+.swift`

### Other components

- **Volunteer**

## Connections

- Volunteer → App routing: uses app (evidence: `README.md`)
- App routing → Main tabs: routes tabs (evidence: `README.md`)
- Main tabs → Home: offers home
- Main tabs → Beach map: offers map
- Main tabs → Goal collection: offers goals
- Volunteer → Record flow: records cleanup
- Record flow → Record form: presents form
- Record form → Record models: collects details
- Record flow → Photo picker: selects photos
- Photo picker → Photo library: loads library (evidence: `Plobby/Plobby/Clients/Photo/PhotoLibraryClient.swift`)
- Record detail → Record service: loads record
- Record service → Supabase backend: reads writes (evidence: `Plobby/Plobby/Clients/Record/RecordClient.swift`)
- Record service → Record models: maps records (evidence: `Plobby/Plobby/Clients/Record/RecordClient.swift`)
- Beach map → Beach service: loads beaches
- Beach service → Supabase backend: queries beaches (evidence: `Plobby/Plobby/Clients/Beach/BeachClient.swift`)
- Beach service → Beach models: maps beaches (evidence: `Plobby/Plobby/Clients/Beach/BeachClient.swift`)
- Goal collection → Goal service: loads progress
- Goal service → Supabase backend: reads goals (evidence: `Plobby/Plobby/Clients/Goal/GoalClient.swift`)
- Onboarding → Authentication: authenticates
- Sign-up → Profile service: updates profile
- Notifications → Supabase backend: reads updates (evidence: `Plobby/Plobby/Clients/Notification/NotificationClient.swift`)
- Authentication → Supabase backend: auth requests (evidence: `Plobby/Plobby/Clients/Auth/AuthClient.swift`)
- Profile service → Supabase backend: profile requests (evidence: `Plobby/Plobby/Clients/User/UserClient.swift`)
- Location → Volunteer: provides location (evidence: `Plobby/Plobby/Clients/Location/LocationClient.swift`)
- Push → Volunteer: delivers alerts
