Youll
Architecture

Dependency Graph

Complete map of dependencies between all 13 Bricks modules and their external frameworks.

Three Levels of Dependencies

Understanding the dependency graph is essential for working with Bricks. Dependencies exist at three levels:

  1. Internal: which Bricks modules depend on other Bricks modules
  2. External: third-party packages fetched via Swift Package Manager
  3. Vendored: pre-built binary frameworks bundled in Bricks/Library/

Each level has different implications for build times, version management, and how customer apps integrate with the platform.

Internal Module Dependencies

The 13 modules form a clear hierarchy. YoullNetwork and TimerShared sit at the bottom with no Bricks dependencies. Core builds on YoullNetwork. Most feature modules depend on Core (and often YoullNetwork). Client sits at the top, orchestrating everything.

Bricks module dependency graph

Client depends on Core, Onboarding, Player, and Profile. Timer depends on both Core and TimerShared. Most Layer 2 modules also depend on YoullNetwork (shown as faded lines).

Full Dependency Table

ModuleDepends OnDependency Count
YoullNetworkNone0 (leaf)
TimerSharedNone0 (leaf)
UITestsNone0 (leaf)
CoreYoullNetwork1
BiometricsCore1
TimerCore, TimerShared2
PlayerCore, YoullNetwork2
ProfileCore, YoullNetwork2
OnboardingCore, YoullNetwork2
CommunityCore, YoullNetwork2
TuyaCore, YoullNetwork2
CoreWidgetCore, YoullNetwork2
ClientCore, Onboarding, Player, Profile4

Dependency Layers

Grouping modules by their depth in the dependency tree:

Layer 0 (Leaf nodes, no Bricks dependencies):

  • YoullNetwork, TimerShared, UITests

Layer 1 (Depends on one leaf module):

  • Core (depends on YoullNetwork)

Layer 2 (Depends on Core and optionally one other):

  • Player, Profile, Onboarding, Community, Tuya, CoreWidget (all depend on Core + YoullNetwork)
  • Timer (depends on Core + TimerShared)
  • Biometrics (depends on Core only)

Layer 3 (Top-level orchestrator):

  • Client (depends on Core + three Layer 2 modules)

Client is the only module with more than two internal dependencies. It imports Onboarding, Player, and Profile directly because these three modules are always active in every customer app. The four optional modules (Timer, Biometrics, Community, Tuya) are never imported by Client. Instead, Client references their interface protocols defined in Core and receives concrete instances at runtime.

External Dependencies

These packages are fetched from remote Git repositories via Swift Package Manager.

Apollo iOS

DetailValue
URLgithub.com/apollographql/apollo-ios
Version>= 1.15.0
Used byYoullNetwork
ProductsApollo, ApolloAPI, ApolloSQLite

Apollo powers all GraphQL networking in Youll. It is only a direct dependency of YoullNetwork, which means other modules interact with GraphQL data through YoullNetwork's API classes rather than importing Apollo themselves.

YoullNetwork also contains a GraphQL sub-package (Swift tools 5.7) that depends on ApolloAPI >= 1.0.0 for generated schema types.

Firebase iOS SDK

DetailValue
URLgithub.com/firebase/firebase-ios-sdk
Version8.7.0 ..< 12.2.0
Used byClient, Onboarding

Firebase is split across two modules with different product imports:

ModuleFirebase Products
ClientFirebaseCrashlytics, FirebaseMessaging, FirebaseRemoteConfig
OnboardingFirebaseAuth, FirebaseDatabase, FirebaseAnalytics

Client uses Firebase for crash reporting, push notification tokens, and feature flags. Onboarding uses it for authentication and user data. Both modules declare the same version range, so SPM resolves them to a single version.

Google Sign-In

DetailValue
URLgithub.com/google/GoogleSignIn-iOS
Version>= 8.1.0-vwg-eap-1.1.0
Used byOnboarding
ProductsGoogleSignIn, GoogleSignInSwift

Used exclusively by the Onboarding module to provide Google account authentication as one of the sign-in options alongside email and Apple Sign-In.

LNPopupController

DetailValue
URLgithub.com/LeoNatan/LNPopupController
Version>= 4.0.0
Used byCore
ProductsLNPopupController

A popup presentation controller used by Core's UI infrastructure, likely for the mini player bar and similar floating UI elements that appear above the tab bar.

Vendored Binary Frameworks

Instead of fetching these frameworks from remote registries, Bricks bundles pre-built .xcframework files in the Bricks/Library/ directory. This eliminates version resolution during builds and ensures every customer app uses the exact same binary.

Core as the Framework Gateway

Core's Package.swift declares the vendored binary targets and re-exports them as library products. Other modules consume these frameworks via .product(name: "SDWebImage", package: "core") rather than declaring their own binary targets. This means Core is the single distribution point for most vendored frameworks.

Client serves a similar role for its own vendored frameworks (AppsFlyerLib, BrazeKit, BrazeUI, PurchaseConnector), though no other module consumes those.

Framework Distribution Table

FrameworkDeclared ByConsumed By
SDWebImageCoreCore, Client, Player, Profile, Onboarding, Community, Tuya
SDWebImageSwiftUICoreCore, Client
SDWebImageWebPCoderCoreCore, Player, Onboarding
libwebpCoreCore, Player
SnapKitCoreCore, Player, Profile, Onboarding
LottieCoreCore, Profile
AppsFlyerLibClientClient
PurchaseConnectorClientClient
BrazeKitClientClient
BrazeUIClientClient

SDWebImage is the most widely consumed vendored framework, used by 7 of the 13 modules for image loading and caching. SnapKit (auto layout DSL) is used by 4 modules.

Unreferenced Frameworks

Two frameworks exist in Bricks/Library/ but are not declared as dependencies in any module's Package.swift:

  • Pulse.xcframework
  • PulseUI.xcframework

These are likely consumed directly by customer apps for network debugging during development, or used only in debug build configurations.

Key Observations

Optional Modules Have Light Footprints

The four runtime-injected modules (Timer, Biometrics, Community, Tuya) have notably fewer dependencies than the always-present modules. Biometrics depends only on Core. This makes them easy to include or exclude from a customer app without pulling in large dependency trees.

Swift Concurrency Migration Is Partial

Three modules (Timer, TimerShared, Biometrics) use Swift tools 6.2 with strict concurrency features (@MainActor default isolation, NonisolatedNonsendingByDefault, InferIsolatedConformances). The remaining 10 modules use Swift tools 5.9. This split reflects an incremental migration toward Swift's structured concurrency model.

iOS Deployment Targets Vary

Most modules target iOS 15. Three modules require iOS 16:

ModuleMinimum iOS
BiometricsiOS 16
CommunityiOS 16
UITestsiOS 16

Customer apps that include Biometrics or Community must set their deployment target to iOS 16 or higher.

No Circular Dependencies

The dependency graph is strictly acyclic. No module depends on another module that depends back on it. This is enforced by the Swift Package Manager's build system, which does not allow circular package references.

For Agents

When working with Bricks module dependencies:

Finding dependency information:

  • Each module's dependencies are declared in its Package.swift at Bricks/modules/{ModuleName}/Package.swift
  • Look for .package(path:) for internal Bricks dependencies
  • Look for .package(url:) for external remote dependencies
  • Look for .binaryTarget for vendored frameworks

Adding a new internal dependency:

  1. Add the dependency in the module's Package.swift under dependencies with .package(path: "../OtherModule")
  2. Add the product to the target's dependencies array
  3. Verify no circular dependency is introduced

Adding a new vendored framework:

  1. Place the .xcframework in Bricks/Library/
  2. Declare it as a .binaryTarget in the module that will manage it (typically Core for shared frameworks)
  3. Add it as a library product so other modules can consume it
  4. Other modules reference it via .product(name: "FrameworkName", package: "core")

Adding a new external SPM dependency:

  1. Add the remote URL and version in the module's Package.swift under dependencies
  2. Add specific products to the target's dependencies array
  3. Prefer version ranges to exact versions for compatibility

Quick reference for common lookups:

  • "What does this module depend on?" Check the module's Package.swift
  • "Who uses this framework?" Search all Package.swift files for the framework name
  • "Can I import module X from module Y?" Check if Y declares X as a dependency. If not, you cannot import it.
  • "Is this module always present?" Client, Core, YoullNetwork, Player, Profile, and Onboarding are always present. Timer, Biometrics, Community, and Tuya are optional.

What's Next

On this page