For the technically curious

How We Built
Subcut

A native iOS app that tracks your subscriptions without tracking you. Here's what's under the hood - and why we made the choices we did.

The Stack

No Electron. No React Native. No web views pretending to be native. Subcut is built the way Apple intended.

SwiftUI

100% SwiftUI with iOS 17+ features. Declarative UI, @Observable macro for state management, spring animations throughout. No UIKit bridges needed.

Core Data + CloudKit

Local-first persistence with iCloud sync. Your data lives on your device first, syncs to iCloud second. Three-tier fallback: CloudKit, local SQLite, in-memory.

RevenueCat

Handles in-app purchases, subscription management, and entitlements. Monthly, yearly, and lifetime plans - all managed through RevenueCat's SDK and dashboard.

Gemini AI

Powers the email import feature. When our local pattern matching (80+ known services) can't identify a subscription, AI extracts the details from email bodies.

Keychain + FaceID

API keys stored in Keychain. Biometric authentication via LocalAuthentication framework. Session timeouts, failed-attempt lockouts, the works.

Mixpanel

Lightweight analytics for understanding how people use the app. Disabled in debug builds. No personally identifiable information is ever tracked.

Architecture

MVVM with dependency injection. Clean layer separation. No spaghetti.

App Layer

Entry point, service initialization, tab navigation

Feature Modules

Calendar, Subscriptions, Import, Settings, Paywall, Onboarding

Core Layer

Models, Services, Persistence (Core Data + CloudKit), Utilities

State Management

Global state lives in an @Observable AppState class - Pro status, selected tab, biometric lock, user settings. Injected via SwiftUI's environment system.

Feature-level state stays in per-screen ViewModels. No bloated god objects. Each screen owns its own state.

Dependency Injection

All services are bundled into a DependencyContainer - a simple Sendable struct - and injected via @Environment. No singletons scattered across the codebase.

Ships with both .live and .mock implementations for previews and testing.

The Import Pipeline

Three ways in. Zero bank credentials required.

Email Import

Gmail OAuth (with PKCE) scans your inbox for subscription receipts. Known services are matched locally against 80+ domain patterns - instant, no API cost. Unknown services get sent to Gemini AI for extraction. Two-stage pipeline: fast local matching first, AI fallback second.

Bank Statement Upload

Upload an .xlsx bank statement and Subcut parses it with CoreXLSX. Recurring charges are detected through pattern matching. No bank login, no Plaid, no third-party access to your accounts. You export, you upload, we parse. That's it.

Apple App Store Import

StoreKit 2 integration pulls in subscriptions managed through the App Store. If you're paying for something through Apple's ecosystem, Subcut knows about it.

Monetization with RevenueCat

We use RevenueCat to handle the hard parts of iOS subscriptions so we can focus on the product.

Soft Paywall Model

Free users can add unlimited subscriptions but only see the first six in full detail. The rest appear blurred - a gentle nudge, not a hard wall.

Tapping a blurred subscription opens the paywall. After upgrading, the blur fades with a smooth animation. It feels like unlocking, not purchasing.

Plans & Pricing

Monthly $1.99/mo
Yearly $9.99/yr (save 58%)
Lifetime $14.99 once

How RevenueCat Fits In

Entitlements

Single "Subcut Pro" entitlement. RevenueCat's SDK checks status on launch and updates in real-time via delegate callbacks.

Paywall UI

RevenueCatUI provides pre-built paywall components. We wrap them with custom context tracking for analytics.

Analytics

Every paywall view and purchase event is tracked with context - which screen triggered it, which feature was gated.

Privacy Is Architecture, Not Marketing

We didn't add privacy as an afterthought. We built the entire app around it.

On-Device Processing

Bank statement parsing happens entirely on your device. Email pattern matching runs locally for 80+ known services. AI is only called for unknown subscriptions.

No Bank Credentials

We never ask for, store, or transmit bank login credentials. No Plaid integration. No third-party financial data access. Period.

Biometric Security

FaceID/TouchID via LocalAuthentication. Session timeouts after 5 minutes. Lockout after 5 failed attempts. API keys stored in Keychain, not in code.

GDPR Ready

Full account deletion support. Export your data in CSV or JSON (encrypted, if you want). Delete everything in one tap. Data erasure, not data hoarding.

By the Numbers

14

Languages supported

27

Currencies

210+

Cancel guides

80+

Auto-detected services

That's How We Built It.
Now Try It.

All of the above powers an app that takes 60 seconds to set up and saves you hundreds a year. Not a bad trade.

Download Free on App Store