SparrowOS
The operations platform a marketing agency runs on: tasks, chat, KPIs, analytics, mail and drive in one place, on the web and as a native Mac app.
My role: Sole developer, end to end: product, backend, web app, Mac app and data pipelines
~70%
more tasks shipped a month once it replaced Sheets and WhatsApp: about 30 before, 50-55 after
~15
people run their day on it across the agency
16
native Mac app releases, shipped through its own updater
49
actions the voice and typed assistant can take
01
The brief
Sage Sparrows runs marketing for D2C, real estate and EV brands with a team of about 15. The work was spread across Google Sheets and WhatsApp threads, and every brand's numbers sat in a different place: Meta, Google Ads, GA4, Shopify, Clarity.
With no in-house performance marketer, the agency needed one place to run its work and one dashboard every brand's ads could be run from. When a campaign stopped spending for days, nobody caught it. That was the kind of gap it had to close.
02
What I built
- Tasks with a reviewer-driven stage flow: every task starts at Briefing, and after each review the reviewer picks the next stage, department and people. Work can be sent back, and Shipped (published) is separate from Done.
- Google Calendar sync for work blocks and deadlines, and a scheduler that respects priority, deadlines and working hours.
- Real-time chat: channels, DMs, threads, mentions, reactions, read receipts, file sharing and deep links to any message.
- A KPI calculator with weighted department scoring, MD scores and profit sharing, with achievements computed automatically from platform data.
- Data pipelines from Meta Ads, Google Ads, GA4, Shopify, Google Trends and Microsoft Clarity, synced daily, plus an ad engine that classifies every ad as TEST, KILL, OPTIMIZE, BREAKEVEN or SCALE.
- Company mail, calendars and file storage on a self-hosted Stalwart server, used from inside the app.
- Push notifications, 6-tier role-based access, Ctrl+K global search, notes with share links and a daily standup board.
- A native SwiftUI Mac app with every page rebuilt, an encrypted local cache, and a system-wide command bar (Option+Space).
- An MCP server so Claude can query the analytics directly.
03
How I built it
First flight on the hosting the agency already hadMarch 2026
A Fastify and MySQL backend, a React and Tailwind web app, Google sign-in with MySQL-backed sessions, and WebSockets for chat and live updates. It runs on the agency's existing cPanel host, so it shipped without new infrastructure.
Fix what the team felt first, then make the numbers rightJune and July 2026
Notifications and login refresh on iPhones and Macs came first. Then analytics became the top priority: I audited all 21 analytics pages, found 19 defects in 4 recurring classes (rates added together, snapshots summed across days, platforms storing the same metric differently, and dates bucketed in the wrong timezone), fixed every one, and folded the 21 pages into one dashboard. A Google Ads sync that had been dead for 13 months, because the API version it used was retired, came back with 25 new fields.
A native Mac app, built from scratchJuly 2026
A webview wrapper was tried and thrown out in favour of real SwiftUI. Native sign-in uses an additive, per-device token that is hashed at rest and can be revoked, so the web's cookie flow stayed untouched. Every page was rebuilt natively, including all 16 analytics dashboards, then audited line by line against the web app.
Make it hard to breakJuly and August 2026
The Mac app gained an encrypted SQLCipher cache, so a hosting hiccup shows slightly stale data instead of an error screen. GA4 turned out to be silently cutting every large report at 10,000 rows; the sync now pages through everything.
Talk to itSeptember 2026
An assistant layer, now 49 actions. The model only names an action and quotes the words; code resolves them, checks permissions, asks for confirmation and executes, with real undo. An audit before release caught 27 of the then 47 tools calling their routes wrongly. Atlas 1.0, a model I fine-tuned, runs it on each person's Mac.
Keep it healthyOctober 2026
A dependency security pass took every audit to zero, and abandoned carts from Shiprocket Checkout now land in Verte's and Alexandre Christie's sales sheets automatically.
04
What it changed
~70%
more tasks shipped a month after replacing Sheets and WhatsApp: about 30 before, 50-55 after
1 page
of analytics instead of 21 separate dashboards
9 brands
56 campaigns, about 110 assets and 120 open tasks in the system on 2 Sep 2026
>30x
the error in one average order value widget before the aggregation fixes
The team runs its work from SparrowOS instead of Sheets and WhatsApp. Management reviews every brand from one analytics page, and campaigns that are switched on but not spending now raise an alarm instead of going unnoticed for days.
Next: moving off shared hosting to a VPS, then Windows, iOS and Android clients on the same server.
05
Inside this entry
The operations platform Sage Sparrows runs on. It replaced scattered Google Sheets and WhatsApp threads with one place for tasks, chat, KPIs and analytics across every brand the agency manages.
- In daily use: on 2 Sep 2026 it held 9 brands, 56 campaigns, about 110 assets and 120 open tasks
- Replaced Google Sheets and WhatsApp as the way the team runs work, taking tasks shipped from about 30 a month to 50-55
- Tasks with a reviewer-driven stage flow, real-time chat (threads, mentions, reactions, file sharing), Google Calendar sync and global search
- Built-in mail and drive on the company's own Stalwart server, private notes with share links, and a daily standup board
- KPI calculator with weighted department scoring, MD scores and profit sharing
- Daily pipelines from Meta Ads, Google Ads, GA4, Shopify, Microsoft Clarity and Google Trends feeding per-brand revenue, traffic, conversion and ad dashboards
- Ad evaluation engine that sorts every ad into test, kill, optimise, breakeven or scale
- Six-tier roles, TOTP-gated impersonation, web push with retries and batching, and a WebSocket build id that reloads clients after a deploy
- Plain-English and voice commands across 49 actions, with an undo log and single-use plan tokens
Full-stack operations platform with real-time chat, task management, KPI tracking, and multi-platform analytics. Used daily by a 15-person team.
KPI scores are updated for March. @Smith can you check the analytics dashboard?
On it. The Meta Ads pipeline synced at 1:00 PM, data looks clean.
Helios campaign is at SCALE status now. ROAS crossed 3.2x
A native SwiftUI client for SparrowOS, built from scratch rather than wrapped around the web app, so the team gets a real dock app and notifications that actually arrive.
- 16 builds shipped to the team through its own updater, the latest being v0.5.0 on 22 Sep 2026
- Every web page rebuilt natively: dashboard, tasks, calendar, chat, mail, drive, notes, KPIs, settings and all 16 analytics dashboards
- Local-first: a whole-database SQLCipher cache keeps the app usable when the server has a bad day
- Hold Option+Space in any app and speak or type a command; dictation and the Atlas 1.0 model both run on the Mac
- Morning standup drafts of each person's day, confirmed and sent to the founder as one summary at noon
- Native sign-in with revocable per-device tokens in the Keychain
- Own release pipeline: versioned builds, DMG, appcast and an in-app updater with release notes; about 27,600 lines of Swift
The Windows sibling of the Mac app: a native WinUI 3 client with the same layouts and navigation, in Fluent Design instead of Liquid Glass.
- Full build plan: SwiftUI to WinUI screen map, tooling versions and a phased build order
- x64 and ARM64 from one C# codebase, shipped as a single MSIX bundle
- SparrowCrypto re-implemented in C# against the same versioned spec, so encrypted local data stays portable between clients
One owned encryption format for company data across every SparrowOS client and the backend: a versioned envelope over standard AES-256-GCM.
- Owns the format, key hierarchy and rotation, and never invents the cipher itself
- A byte-for-byte spec that web, macOS, iOS, Android, Windows and the server can all implement
- Zero dependencies on every platform: Node crypto, CryptoKit, javax.crypto, .NET and WebCrypto
The company's own workspace instead of a Google Workspace subscription: email, calendars and file storage self-hosted on Stalwart, with SparrowOS as the interface.
- Runs the company's mail domain, and sends the storefront checkout alerts
- Stalwart on the company VPS serving IMAP, SMTP, JMAP, CalDAV, CardDAV and WebDAV, so Apple Mail and phones sync natively
- Web mail inside SparrowOS over JMAP, with attachments, snooze and shared team inboxes
- Mailbox admin in SparrowOS: create and remove accounts with storage quotas, and manage shared inboxes
- Sparrow Drive: each person's files on Stalwart over WebDAV, with share links minted by SparrowOS
- DKIM-signed mail with SPF and DMARC, after finding the rotating-key trap that lets Gmail silently drop mail
- Began as a small self-built Node SMTP service, replaced by Stalwart once a full workspace was in scope
A Claude-powered ad-ops assistant inside SparrowOS. The ad engine decides, a person confirms, and our code executes; Claude never fires anything itself.
- Creates campaigns, ad sets and ads from Google Drive assets, always paused for review, including carousel, dynamic, WhatsApp and partnership formats
- 27 typed change proposals; deletes, objective changes and anything touching PII are refused outright
- Confirmation is a backend event Claude cannot create
- First real ad created live through it
Lets Claude Code ask the live SparrowOS server analytics questions directly, instead of exporting a 3.5 GB database dump every time.
- Read-only, and scoped by the same roles and brand access as the apps
- Token kept in the macOS Keychain, expires after 90 days and can be revoked from Settings
- Tools for metrics, fact rows, brand sources and full reports
In-house replacements for Zapier-style tools: Meta lead ads and Shiprocket abandoned carts land straight in the sales teams' Google Sheets.
- 698 Meta leads delivered into the sales team's sheets since it went live on 22 Jul 2026
- In the pipeline's log to 6 Nov 2026, 693 of 698 live leads reached the sheet within 30 seconds, half within 11. Two took a few minutes, and the nightly sweep caught the other three
- Real-time leadgen webhook with HMAC-SHA256 signature checks, a one-time backfill and a daily reconciliation sweep
- Answers Meta fast, then fetches and writes each lead from a queue with retries
- Abandoned carts from Shiprocket Checkout captured, mapped and written per brand
A customer-facing warranty claim flow for watch brands, served from SparrowOS into each Shopify store through the App Proxy.
- Phone sign-in with a WhatsApp one-time code
- Looks up the customer's Shopify order, then logs the claim to email and Google Sheets
- Every request verified with Shopify's App Proxy HMAC