As you begin customizing StarterAppKit for your own purposes, you’ll likely want to tailor the initial views presented to your users. One of the first places you might start is by modifying or replacing the Base/Home view.
By default, the Base view is included as an example entry point to various pre-built views and features in StarterAppKit. If a user is authenticated, this view acts as the “home” screen; if not, the user sees the authentication screen. The Base view also serves as the primary entry point for authenticated deep links, helping to route the user to the correct destination based on incoming URLs.
The Base view is introduced in InitialView.swift
, which determines what to present based on the user’s authentication state. Here’s the relevant snippet:
// InitialView.swift struct InitialView: View { @StateObject var vm: InitialViewModel var body: some View { ZStack { Color.clear Group { switch vm.authState { case .undetermined: EmptyView() case .loggedIn: if let paths = vm.navigationPaths, !paths.isEmpty, paths[0] == "home" { // If deep linking to "home" BaseView(remainingPaths: Array(paths.dropFirst())) } else if let directPath = vm.currentPath { // Direct navigation to a specific view based on deep link destinationView(for: directPath) } else { // Default home screen if user is logged in BaseView(remainingPaths: nil) } case .loggedOut: // If not logged in, show SignInView or handle non-auth deep links if let path = vm.currentPath, !(AppDeepLink(rawValue: path)?.requiresAuth ?? false) { destinationView(for: path) } else { SignInView(vm: AuthViewModel()) } } } } .toast(manager: vm.getAppManager()) } @ViewBuilder private func destinationView(for path: String) -> some View { switch path { case AppDeepLink.confirmAuth.rawValue: ConfirmAuthView(vm: ConfirmAuthViewModel(token: vm.parameters["token"] ?? "")) case AppDeepLink.resetPassword.rawValue: ResetPasswordView(vm: AuthViewModel(token: vm.parameters["token"] ?? nil)) default: EmptyView() } } }
myapp://home/profile
), the Base view may be responsible for initiating navigation to the correct subview.Edit BaseView.swift
directly:
If you’re mostly satisfied with the current setup, you can open BaseView.swift and remove or adjust code that’s not needed.
Create Your Own View and Update InitialView.swift:
If you’d prefer a fresh start, create a new SwiftUI view (e.g. MyCustomHomeView.swift
) and then replace BaseView(remainingPaths: ...)
calls in InitialView.swift
with your custom view.
Let’s assume you’ve created a new home screen view called MyCustomHomeView.swift
.
remainingPaths
: An array of path segments extracted from a deep link (e.g. myapp://home/profile
→ ["home", "profile"]
)nextDestination
: A computed property that identifies the next path segment and the remaining segments after it.shouldNavigate
: A state variable that triggers navigation once the view appears and a next destination is detected.CustomNavigationLink
: Used to initiate navigation to the target view identified by the next deep link path.// MyCustomHomeView.swift import SwiftUI struct MyCustomHomeView: View { var remainingPaths: [String]? @State private var shouldNavigate = false // Determine if there's another destination in the deep link paths var nextDestination: (path: String, remaining: [String])? { guard let paths = remainingPaths, !paths.isEmpty else { return nil } // Take the first path as the next destination, and pass along the rest let next = (paths[0], Array(paths.dropFirst())) return next } var body: some View { VStack(spacing: 20) { Text("Welcome to My Custom Home!") .font(.largeTitle) .padding() // Add your own UI elements here (buttons, lists, etc.) } .onAppear { // If there's a next destination (e.g., "profile"), prepare to navigate if nextDestination != nil { shouldNavigate = true } } .background( Group { if let next = nextDestination { CustomNavigationLink( shouldNavigate: $shouldNavigate, destination: { // Navigate to the appropriate screen based on the next path switch next.path { case "profile": return AnyView( UserProfileView( vm: UserProfileViewModel(), remainingPaths: next.remaining ) ) // Add more cases here for other deep link paths default: // If the path doesn't match a known route, return a fallback view return nil } }, label: { EmptyView() } ) } } ) } }
In InitialView.swift
, replace the references to BaseView
with MyCustomHomeView
. If the user is authenticated and there are no deep link paths, your custom home view will appear by default. If there are deep link paths, MyCustomHomeView
uses the logic above to navigate to the correct destination.
// InitialView.swift (replacing BaseView with MyCustomHomeView) case .loggedIn: if let paths = vm.navigationPaths, !paths.isEmpty, paths[0] == "home" { MyCustomHomeView(remainingPaths: Array(paths.dropFirst())) } else if let directPath = vm.currentPath { destinationView(for: directPath) } else { MyCustomHomeView(remainingPaths: nil) }
myapp://home/profile
. Your custom home view should automatically navigate to UserProfileView, thanks to the deep linking logic you replicated.