Warmbly iOS
Native SwiftUI companion app for the Warmbly dashboard, for iPhone. Covers the mobile-relevant dashboard surface: unified inbox (read, reply, snooze, review the inbox agent's drafted replies and send them as written or refine them in the full composer with its AI tools, draft a reply from the thread with AI or ask Remie to summarize it, and the web's sidebar: Mail folders, Views, Mailboxes, Labels and Tags as sections that fold and move, with Favorites, hidden and reordered rows synced to the account through unibox_rail), mailbox accounts with warmup monitoring and controls (every mailbox shows its profile photo and the service that runs it, from Google Workspace and Microsoft 365 to Zoho or the vendor it was imported from), campaign monitoring with start/stop (each row shows how far through its leads it is, the campaign page splits its leads by outcome and charts sends, opens and replies over 7 to 90 days in the same scrubbable chart as Home, and the drawer filters by status, manages folders and sorts), contacts (each row shows the last thing that happened with them, rings the avatar on a fresh reply or click, groups under letters or dates by the sort, and swipes to label, add to a campaign, unsubscribe or delete) with the 360 view (an outreach journey from sent to replied and one-tap email, campaign and note actions), analytics (a scrubbable trend, rates against the previous period, a reply funnel, deliverability rates against their safe ranges, warmup against its ramp and where it landed, and every mailbox's health), CRM (a pipeline card with the win rate and each stage's value, deals you swipe to win; tasks with a ring for today and a check that ticks itself off, celebrating when the day is clear; meetings with a live countdown to the next call and a join button, grouped by day), templates (with their merge fields and an email-style preview), a live activity timeline of who changed what, and settings: a hub showing your workspace at a glance (mailbox health, the week's sends, open deals, tasks and meetings, members online) beside profile, notifications, security, billing and appearance, each its own page (a name card that saves in place, a password change with a strength meter, every signed-in device, account deletion with its 30-day grace window, sign-in protection, the plan with its renewal and what it includes, usage against the limits the server enforces, AI credit spend by day and by feature and a referral code to copy or share, the roster with who is online and pending invites, and an inbox of alerts grouped by day with its delivery switches). Realtime by default: the app joins the Phoenix websocket and refreshes lists live off the same AUDIT_CREATED spine the web uses, including org presence (who is viewing/editing which record).
Requirements
- Xcode 26 or newer (the project uses the folder-synchronized project format and an iOS 26 deployment target).
- A running backend. For local dev:
make infra,make backend, andmake realtimefrom the repo root (the realtime service powers live updates and presence; the app degrades gracefully without it).
Running
- Open
ios/Warmbly.xcodeprojin Xcode. - Select the Warmbly scheme and an iOS 26 simulator, then run.
- On the login screen, tap the gear and pick Local development (every build starts on Warmbly Cloud). That points the app at
http://localhost:8080(it calls<origin>/v1) and fills in the captcha bypass token local backends accept, since the simulator can't use App Attest. On a physical device, choose Self-hosted and enter your Mac's LAN address instead. - Sign in with a seeded user (
make seedcreatesdev@warmbly.com/password123) or register from the app. Password login is two-step: credentials, then an emailed 6-digit code (visible in Mailpit athttp://localhost:18025during local dev).
For a full local development walkthrough (running the stack, the first-run flow, physical devices, and troubleshooting), see DEVELOPMENT.md.
Releasing
Merges to main that touch ios/ upload a build to TestFlight through .github/workflows/ios-release.yml; submitting a build to the App Store is a manual step in App Store Connect. Setup, secrets and the release checklist are in DEVELOPMENT.md.
Architecture
Warmbly/Core/Networking/APIClient.swift: async client for the/v1API. Bearer auth, single-flight token refresh (refresh tokens are single-use server-side), one retry on 401,Idempotency-Keyon mutating calls that need it.Warmbly/Core/Session/SessionStore.swift: login (password + OTP + optional TOTP), registration, org selection. The active org is server-side session state, so the store re-POSTs/organization/switch/:idonce per launch, mirroring the web's OrgGate.Warmbly/Core/Realtime/: a Phoenix Channels client speaking the V1 object-frame serializer (vsn=1.0.0) overURLSessionWebSocketTask, with 25s heartbeats, an 8s reply watchdog, resume vialast_seq, and jittered reconnect backoff.RealtimeServicemaps events onto invalidation "pulses" that views observe, and tracks org presence.Warmbly/DesignSystem/: the marketing site's design language translated to native iOS. A clean canvas with hairline borders instead of shadows, near-black pill actions (InkButtonStyle,OutlineButtonStyle), medium-weight display type with tight tracking and the site's two-tone headings (TwoToneTitle), system-font meta text with tabular digits (WFont.meta;WFont.codeonly for real code), sentence-case section labels (EyebrowLabel), one Liquid Glass header for every list tab (GlassHeaderBar), one workspace header for every drawer (DrawerWorkspaceHeader), one scrubbable sends, opens and replies chart (TrendChart, withCountUpTextand the staggeredrevealentrance), sky kept for data and live state, status tones matching the web (emerald running, amber paused, rose issues), and the site's photo frames (PhotoFrame). Sign-in and onboarding sit on the brand backdrop (SkyBackdrop): the site's sheer sky photo, with a night version of the same photo in dark mode (theSheerSkyasset's dark appearance), andWTheme.onSkyfor what is drawn on it. The launch screen and splash follow the theme too. Every color is a light/dark pair inWTheme.Warmbly/Features/: one directory per feature; each screen loads with.task, reloads on realtime pulses, and supports pull-to-refresh.
The Xcode project uses PBXFileSystemSynchronizedRootGroup, so new Swift files under Warmbly/ are picked up automatically; the pbxproj never needs editing for added files.
Known limits
- Adding a mailbox takes an app password (Gmail walks through creating one; Zoho, Yahoo, iCloud, Fastmail and other common hosts get their servers filled in from the address), an admin grant over a whole Workspace domain or Microsoft 365 organization, an inbox vendor's API key (InboxKit, Zapmail, Mailforge and the rest of the dashboard's catalog), a CSV, spreadsheet or pasted list, or a mailbox already on a linked Warmbly Cloud workspace. Bulk sources let you pick or preview the mailboxes first, then follow the import live. There is no per-mailbox Google or Microsoft sign-in, and setting up a new admin grant happens on the dashboard, since it needs the provider's admin console. Campaign sequence editing also stays on the web.
- The app starts in light mode. Settings > Appearance, and the gear on the sign-in screen (before anyone signs in), switch it to dark or to follow the system; the choice is stored on the device (
AppearancePreference). Dark mode uses zinc neutrals on charcoal.