Skip to main content
Version: 1.0.0

Structure

Details on architecture, folders, main files, and asset management for the ARShades iOS app and its App Clip.


Architectural overview

  • Pattern: MVVM + Interactors (Use-Cases)
  • UI: SwiftUI (with small UIKit wrappers where necessary)
  • Rendering: ARKit + RealityKit
  • Data: Firebase (Firestore, Storage, Dynamic Links, Messaging, App Check), optional Realm cache (full app only)
  • Navigation: Side menu; deep links drive state hydration before presenting Try-On
  • App Clip: Smaller surface that mirrors core Try-On flow

Top-level layout

Top-level layout

ARShades/
├─ ARShadesFramework/ # Shared domain: ViewModel contracts, LiveData, Utils, Models, Extensions
├─ ARShades/ # Full app target (SwiftUI views, screens, resources)
├─ ARShades Clip/ # App Clip target (mirrors minimal set of app layers)
├─ Packages & Pods # Swift Package Manager + CocoaPods (Firebase, Realm, etc.)

Shared framework (domain & utilities)

ARShadesFramework/

  • ViewModel/

    • VM_Protocol — common VM interfaces used across screens.
  • Database/ (domain models & persistence helpers live here together with Models below)

  • Utils/

    • MemoryUtils, ModelUtils, ARDownloadUtils, KeyboardResponder, Reachability
    • DynamicLinkHelpers/: DeepLinkKey, DynamicLinksFuncs, DeepLinkHandler
    • ActivityIndicatorView
    • Protocols/: IDownloadUsdz (3D asset download abstraction)
  • Live_Data/

    • TagsLiveData, SystemData, SizesLiveData, SystemLiveData, LineLiveData, ModelLiveData, BrandLiveData, NotificationLiveData, ObservableGlasses
    • Purpose: observable singletons that hold app-wide reactive state published to SwiftUI.
  • Extensions/

    • DeviceExtension, ThreadExtension, ViewExtension, StringExtension, ColorConverter, DoubleExtension, DateExtension
  • Model/

    • Persistent & domain objects: Catalogue, Preferito, Metrica, PrivacyPolicy, Notifica, TakePicTemplate, CatalogueProduct, CatalogueVariant, Brand, Occhiale, Tag, Linea, Modello, Taglia, AppConfig, Skin
    • Models_Interface/: protocol forms (IOcchiale, ITaglia, IMetrica, IBrand, IModello, ILinea, ITag)

Rendering container

ARViewContainer/

  • ARViewContainer.swift — SwiftUI ↔ RealityKit bridge. Hosts ARView, manages ARSession with a Coordinator.
  • Responsibilities: face-anchor updates, model load/reload, animation controls, lighting tuning, metrics computation callbacks.

Full app (UI, screens, composition)

ARShades/

  • LiveData/ — app-target specific observable data (CardsLiveData).

  • Extensions/ — UI/image helpers (ImageExtension).

  • Constants/ — app-wide constants.

  • Components/ (reusable SwiftUI building blocks)

    • Buttons/ButtonFavouriteCard
    • Badge/Badge
    • Notification/NotificationItem
    • Catalogue/Catalogue_Item
    • MetricsMenu/MenuMetrics
    • ColorDots/ColorDot, DotList
    • GlassesCard/CardList, CardExplore
    • GeneralViews/GeneralView
    • SideMenu/SideMenu, SideMenuPageChooser, SideMenuModel, SideMenuOptionView, SideMenuHeader
    • metrics_menu/WebView3D
    • GlassesMenu/GlassesMenu, CarouselView
    • ItemSize/, Buttons/, Filters/, ShareSheet/, ItemSlider/, SearchBar/, IconsMetrics/, MetricRow/
  • Resources/

    • Launch assets (e.g., splash_ar_shades), shared imagery, App Clip assets.
  • App_Start/

    • AppMain (SwiftUI @main), AppDelegate, AppStart, AppDelegateMethods
    • Handles Firebase config, App Check, notifications, deep-link entry, session updates, and PP/T&C gating.
  • Interactors/

    • Interactor_Interfaces/: GlassesInteractorProtocol, TagsInteractorProtocol, ModelsInteractorProtocol, FirebaseInteractorProtocol, DynamicLinksInteractorProtocol, CardsInteractorProtocol, ISigninInteractor
    • Implementations: GlassesInteractor, TagsInteractor, ModelsInteractor, FirebaseInteractor, NotificationInteractor, CardsInteractor, SigninInteractor, InteractorsContainer (DI/locator)
  • Repository/

    • Firebase/
      • signin/: FirebaseSigninPassword, IFirebaseSigninPassword
      • protocols_read/: IRead*Repository (Glasses, Brand, Line, Size, Model, Category, Privacy, AppVersion)
      • read/: FirebaseRead* concrete readers (Glasses, Products, Catalogue, Variant, Brand, Line, Size, Model, Category, PrivacyPolicy, AppVersion, AppConfig)
      • protocols_write/: SessionFirebaseWrite
      • write/: FirebaseServices, FirebaseDownloadUtils
    • Purpose: network/data layer mapping Firestore documents & Storage assets to domain models.
  • Session/

    • ContatoriBrand, SessionFirebase, UserSession, SessionMethods, GlassesSession, ModelSession
    • Tracks user sessions, counters, timestamps; writes session docs via FirebaseServices.
  • Utils/

    • Permissions, FacialMetricsComputer, RealmUtils, DownloadUsdz, DownloadImage
  • Screens/ (SwiftUI screens grouped by feature)

    • NewSkin/ & 2024Skin/ — skin-themed UIs (menus, dots, cards, button sets, etc.)
    • ExploreScreen/ExploreScreen
    • SplashScreen/SplashScreenPage, SplashScreenViewModel
    • NotSupportedDevice/ViewNotSupported
    • Notifications/NotificationsPage, NotificationScreenViewModel
    • WorkInProgress/
    • Favourites/FavouritesPage
    • Catalogue/CataloguePage, CatalogueScreenViewModel
    • ProductPage/ProductPage, ProductPageFavourite
    • FacialMetrics/ (+ Controllers/ for UIKit wrappers)
    • TermsAndConditions/TermsAndPrivacyPage
    • ModelViewer/ModelViewer
    • ContactPage/ContactPage, ContactScreenViewModel
    • TryOn/TryOnPage, TryOnScreenViewModel
    • Filters/FilterPage, CategoryPage, TagPage
  • ViewModel/

    • AppState, MetricsViewModel, VMGlobalInstance, AppConfigViewModel
  • GoogleServiceInfoPlists/ & InfoPlist (localized) — per-environment Firebase configs & Info.plist localizations.

  • Assets/ & Localizable/ — shared resources and translations.

  • ARShadesKit/, Tests/ — frameworks and unit/UI tests (where applicable).


App Clip target

ARShades Clip/

  • Repository/Firebase/
    • signin/: FirebaseSigninPassClip
    • write/: SessionFirebaseWriteClip
    • read/: App-Clip-scoped readers (FirebaseRead*Clip)
    • FirebaseFunctions: helpers scoped to App Clip
  • Model/
    • Rest/ (DTOs for lightweight payloads), Model_Not_Persistent/ (session-only structs)
  • App_Start/AppStartClip
  • Interactors_Clip/GlassesClipInteractor, CardsInteractorClip
  • ViewModel/AppStateClip
  • Utils/DownloadUsdzRest
  • Views/
    • Composed_Widgets/ (DotList)
    • Widgets/ (AppClip_FAB/Card)
    • Pages/ (AppClipGeneralView, SplashScreenAppClip, TryOnClip, ProductPageClip, ViewNotSupported, plus badges, item size, and new-skin components)
  • Localizable/ & InfoPlist/ — localized App Clip plists

The App Clip carries only the minimal sets required for deep-link try-on (parse c/m, fetch lightweight catalog/variant, render model, present CTA to open the full app).


Asset management

  • 3D models (USDZ)

    • On-demand downloads via DownloadUsdz (full app) and DownloadUsdzRest (App Clip).
    • Retry & attach to RealityKit scene inside ARViewContainer.Coordinator.
    • Periodic cleanup: deletion of cached USDZ after a retention window to control disk usage.
  • Images

    • Remote images cached via Kingfisher in lists, cards, and carousels.
    • Notification images fetched from Firebase Storage when present.
  • Shared bundles

    • Assets/, SharedAssets/, ClipAssets/ separate full-app vs App Clip resources.
  • Localization

    • Localizable/ and localized InfoPlist files (EN/IT/ES/DE/FR).

Build & targets

  • App Groups: group.arshades.appClipMigration for small state sharing between app and App Clip.
  • Associated Domains: applinks:safilo.arshades.it, applinks:spaarkly.page.link, appclips:safilo.arshades.it for Universal Links & App Clip invocation.
  • Background Modes: Remote notifications enabled in the full app.
  • Signing: Team Spaarkly srl, bundle it.spaarkly.ARShades-demo, automatic signing.

Package dependencies (SPM)

  • Firebase (Analytics, Crashlytics, Firestore, Storage, Messaging, Dynamic Links, App Check)
  • Realm / RealmSwift (full app only)
  • DeviceKit, Kingfisher, swift-markdown-ui, SwiftUIGIF
  • Low-level Firebase deps (gRPC, GoogleUtilities, Promises, etc.) are pulled transitively.

Data flow (high level)

  1. StartupAppMain/AppDelegate configures Firebase & App Check.
  2. No deep linkAppConfig (Firestore) defines visible catalogues → BrandsTry-On (first 30 products).
  3. Deep link (c, m) → hydrate catalogue/variant/product/siblings → Try-On; if c not in AppConfig, persist to Realm for future Brands listing.
  4. Interactions → Interactors call Repository readers/writers → LiveData updates → SwiftUI views react.
  5. ARARViewContainer manages face anchors, model load, lighting, animations.

Naming & conventions

  • Files & folders reflect feature areas (TryOn, Catalogue, Notifications, etc.) and shared components (Components/*).
  • Protocols prefixed with I* in domain interfaces; LiveData suffix for observable singletons.
  • Repositories named FirebaseRead* / FirebaseRead*Clip for clarity across targets.
  • ViewModels live under ViewModel/ and are injected via VMGlobalInstance or feature initializers.