Canonical release notes:
RELEASE_NOTES.md in the boilerplate repo. This guide is the step-by-step version.1. Toolchain
v2.0 uses iOS 26 SDK symbols (Glass, glassEffect, GlassEffectContainer) that older toolchains cannot compile, regardless of #available checks.
Required:
- macOS 15+
- Xcode 26.2+ (Swift 6.0)
- iOS 17+ runtime (unchanged)
26.3 via .xcode-version. If you use xcodes or asdf-xcode, run xcodes install (or asdf install xcode) inside the repo to match.
2. Apply the Supabase migration
v2.0 ships a new SQL migration that fixes a permissions gap on the conversation-stats trigger.3. Redeploy the ai edge function
The Edge Function was updated alongside the migration. Redeploy it so the new version picks up the fix:
4. Install the secrets pre-commit hook
v2.0 ships a pre-commit hook that blocks accidental secret commits (the hook lives in.githooks/). Enable it once per clone:
5. Reapply downstream customisations
A lot of oversized files were split into extension siblings to stay under the new ≤ 400-line rule. Public entry points are unchanged, but if you customised any of these files, your edits may now belong in a subview or sibling file.| Touched in v1.9 | Where the content lives now |
|---|---|
ProfileView.swift | Views/Profile/*.swift (composition root + section files) |
SettingsView.swift | Views/Settings/*.swift (≤ 125-line root + one file per section) |
EmailSignUpView.swift | Views/Auth/EmailSignUp*.swift |
SessionManager.swift | +SignIn, +Refresh, +Persistence extensions |
L10n.swift | L10n+<Namespace>.swift per nested enum |
ChatViewModel.swift | ChatViewModel+Memory.swift for history/memory |
git log the file, find the function you edited, grep for it in the new tree, port the change.
6. Fighting-glass cleanup
This is the biggest source of visual regressions when upgrading. On iOS 26, SwiftUI handles sheet and container materials for you. If your downstream code piles manual backgrounds on top, you block the Material SwiftUI already provides and you fight Liquid Glass on iOS 26. Remove these patterns from your own views:.background(DSColors.background)on SwiftUI containers (NavigationStack,Form,List, sheets,TabView).DSColors.background.ignoresSafeArea()stacked under sheets or full-screen covers..background(.black)or.background(Color.clear)under.presentationBackgroundon sheets..scrollContentBackground(.hidden)on forms that already use.formStyle(.grouped)..groupedalready does the right thing on iOS 26.- Explicit
.safeAreaInset(edge: .bottom)gutters under aTabView. The tab bar’s own inset is already respected.
.saiGlass(.regular)when you need glass on a custom view.SAIGlassContainer { ... }when multiple glass surfaces sit near each other..saiScrollEdgeGlass(_:)for scroll-edge treatment under nav and input chrome..saiTabBarMinimize(.onScrollDown)if you want iOS 26 tab bar minimisation (it is a no-op on iOS 17–25).
7. Paywall CTA theming
Paywall CTAs in v2.0 use the standard system styles:.background(), switch to .tint():
.tint() lets the standard button style render the glass-aware surface correctly on iOS 26, and still picks up the correct Material on iOS 17–25.
Quick verification checklist
After the upgrade, run through this list before shipping:- App builds under Xcode 26.2+ with zero Swift 6 warnings.
- Supabase migration ran cleanly (
supabase migration listshows20260408000000_fix_conversation_stats_auth). - The
aiEdge Function returns a streaming response end-to-end. -
git config core.hooksPathreturns.githooks. - Sheets, paywall, settings, and chat all look right on iOS 26 (Liquid Glass) and iOS 17–18 (Material fallback).
- No remaining
.onReceive(...)onToastCenterorDeepLinkBusin downstream code; migrate to.onChange(of:). - No remaining
.background(DSColors.background.ignoresSafeArea())under containers.
Related
Changelog
Full v2.0.0 release entry
Liquid Glass API
SAIGlass, modifiers, containerArchitecture
Swift 6 concurrency model + ≤ 400-line rule
Troubleshooting
Common upgrade errors and fixes
