posts

Tobi Goes to Shipaton

I submitted Tobi to RevenueCat's Shipaton.

Last week, I submitted Tobi to RevenueCat’s Shipaton. This was the whole goal with Tobi, get it submitted to Shipaton as something I would want to use and use it to test out some big theories I’ve been seeing in the indie developer space, like hard paywalls and a longer onboarding. Throughout the last 2 months, I learned that those 2 probably work when you have a lot of people coming into the app. Due to Tobi’s lack of users or downloads, I didn’t really see an impact either way, so I decided to make it freemium with a shorter onboarding. The idea is to let more people get into the app as quickly as possible.

Numbers

Last month:

This month:

Experiment Report

From September 6 to 19, I tested the hard paywall against freemium with 3 free tasks on Tobi. People weren’t converting either way, so I was hoping to get more people through onboarding with freemium. In PostHog, 15 people got the hard paywall and 12 got freemium. One person in the freemium group set up a household within 7 days, and nobody in the hard paywall group did. That’s not enough people to call a winner, but freemium showed me more clearly where people drop off, so I rolled it out to everyone.

I unfortunately still haven’t seen many people complete onboarding. They usually drop on the first screen of onboarding, where you name your home. Next, I’ll remove that screen from setup because maybe people are wondering why they need to name the home.

Technical Spotlight

Tobi 1.5.0 added Siri, Shortcuts, and Spotlight support. Here’s the pattern, made generic: an “Open a tab” action for any SwiftUI app.

// OpenTabIntent.swift
import AppIntents
import Observation

enum AppTab: String, AppEnum {
    case home
    case search
    case settings

    static var typeDisplayRepresentation: TypeDisplayRepresentation {
        TypeDisplayRepresentation(name: "Tab")
    }

    static var caseDisplayRepresentations: [AppTab: DisplayRepresentation] {
        [
            .home: DisplayRepresentation(title: "Home"),
            .search: DisplayRepresentation(title: "Search"),
            .settings: DisplayRepresentation(title: "Settings"),
        ]
    }
}

@MainActor
@Observable
final class AppRouter {
    static let shared = AppRouter()

    var selectedTab: AppTab = .home

    func open(_ tab: AppTab) {
        selectedTab = tab
    }
}

struct OpenTabIntent: AppIntent {
    static var title: LocalizedStringResource { "Open a tab" }
    static var supportedModes: IntentModes { .foreground }

    @Parameter(title: "Tab")
    var tab: AppTab

    func perform() async throws -> some IntentResult {
        await AppRouter.shared.open(tab)
        return .result()
    }
}

struct MyAppShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: OpenTabIntent(),
            phrases: [
                "Open \(\.$tab) in \(.applicationName)",
            ],
            shortTitle: "Open tab",
            systemImageName: "square.grid.2x2"
        )
    }
}

Put this in one file in your app target and swap in your own tabs. You never call the intent yourself. Xcode picks up the intent and its phrase when it builds the app, so saying “Open Settings in” plus your app’s name works in Siri, and the action shows up in Shortcuts and Spotlight. In your root view, add @State private var router = AppRouter.shared and use TabView(selection: $router.selectedTab). Just remember, supportedModes needs iOS 26 or later.

It helps because the intent never touches your views, which might not be on screen when it runs. It only sets the tab on AppRouter, and your view picks it up when it appears.

This Month’s Focus

In October, I am focused on the following:

// open to work

I'm looking for my next thing, whether that's full-time, consulting, or a long-term contract. If you're building something where the details matter, I'd like to hear about it. Send me an email.

May 1, 2026 shipping notes
From Screenshots to Downloads
Screenshot changes improved Camp Notes discoverability and pushed better growth this month, while onboarding and paywall tests still need more signal.
Apr 4, 2026 shipping notes
Numbers Up, Lessons Mixed 📊
New users nearly 5x'd in Camp Notes, plus a technical trick to keep everyone on the latest version.
Mar 6, 2026 shipping notes
New app launched but basically no users
February 2026 recap and what I'll be doing in March.