Journey Studio Goes Mobile, a Spanish Coach That Talks Back, and Shorts From One Recording
Last week was about new foundations. This week was about getting things off my desk and out to people. Journey Studio left the Mac, and its renders now land on YouTube. language-learn got its first session where an AI coach actually talks you through a lesson. And First Cut, the video editor I started last week, turned into an app I open from the Dock.
Journey Studio: From a Mac Tool to TestFlight
Journey Studio is the companion app I use to turn Mind Journeys sessions into long-form videos: the audio journey, backdrops, slow Ken Burns motion and a grade over the top. Until this week it was a Mac-only tool I ran from the command line. I split the work into five cards and got through all of them.
The first card was the boring one. I moved the
engine (models, audio, video, the render coordinator) into a platform-neutral
StudioCore folder that imports neither AppKit nor UIKit. I didn't make it a
Swift package, because that would mean marking about 4,000 lines of API
public for no real benefit. Each target compiles the same folder instead.
A tiny check target fails the build if anyone sneaks an AppKit import into
the engine.
Everything after that built on it:
- Formats: 16:9, 9:16, 4:5 and 1:1, so one journey can be cut for YouTube, Shorts and Instagram.
- Moving backgrounds: GIFs, APNG, animated HEIC and video clips now work as slides, with the same Ken Burns, dissolve and grade as stills. The encoder still reuses frames for runs of stills, so the cheap case stays cheap.
- Generated backdrops: the code-drawn gradients looked empty, so backdrops now come from OpenAI's image model. The key lives in the keychain, never in project files.
- iPhone and iPad: same SwiftUI views, with rendering on
BGContinuedProcessingTask, so you can lock the phone and let it work. It checks free space first and backs off when the device gets hot. - TestFlight: build 1.2 is up for both platforms, with a sandboxed Mac build and a new icon that's clearly a sibling of the Mind Journeys one.
I also rebuilt the Journey tab to match the Mind Journeys builder. Two apps that build the same thing shouldn't feel different.
Then I closed the loop. There's a small Python script that uploads finished
renders to the Mind Journeys channel as private videos, using resumable
16 MB chunks and refreshing the token mid-upload so multi-hour sleep videos
survive a dropped connection. It refuses to upload anywhere except that one
channel. The site got a /videos/ page, and it keeps the no-cookies promise:
each card is our own thumbnail, and the youtube-nocookie player only loads
when you press play.
Mind Journeys: Onboarding That Ends in a Real Journey
Last week I added per-screen analytics because about a third of installs never finish onboarding. This week I changed what onboarding is. The last four screens used to be configuration. Now you build your first journey: shape a step, choose what comes next, set the scene, hear it, then save it. Saving is the only way out, so everyone reaches the paywall holding something they made. That's 1.6 (1) on TestFlight now.
On the marketing side, I did an SEO health audit of mindjourneys.app, with a
dependency-free seo:check crawl I can run monthly. I also wrote a weekly
funnel report from PostHog. I kept website, Search Console and App Store
numbers as three separate sources on purpose. Combining them into one
conversion ratio would look neat and be wrong.
language-learn: The Coach Talks Back
The scenario model from last week got its first real test. A curated guided session now runs in one LiveKit room: an English intro, a Spanish listening dialogue, spoken comprehension questions, live Spanish practice and an English recap. It ships dark behind a server flag and an allowlist.
Then I ran it on my phone, and it was humbling. Only the listening check got
saved. English speech-to-text heard "tostada" as "to start", and the evaluator
decided I'd practised "mostly in English". The cause:
ChatMessage.textContent in the LiveKit SDK is a class getter, and an
object spread doesn't copy getters. So every turn was recorded with empty
text and thrown away.
The next PR fixed the experience. Coach questions can't be interrupted any more. The agent starts listening 1.5 seconds into each question, so an early answer still counts. After 12 seconds of silence it re-prompts instead of waiting. Each answer gets spoken feedback, judged by a small fast model against the authored answer.
The tutor also now adapts to what you've shown it before. It gets at most three targets with a focus (reinforce, review, explore, stretch), capped at 2 KB and with no scores or transcripts. I also built a phone-friendly admin review queue where the AI makes the first pass. There are 1,389 auto-generated Spanish targets and only 63 are published, so reviewing has to be quick.
First Cut and Calculador Neto
First Cut now has a project library and server-side state, so closing the browser doesn't lose your work. It also runs as an Electron Mac app, which imports recordings by path as APFS clones and never moves the originals. The bigger feature is shorts. One recording session gives you the long edit plus up to five 9:16 shorts, cut from the edited main cut, so trims and removals carry over. The AI picks the moments. The pacing, punch-ins and captions are deterministic code.
Calculador Neto got one focused change: worked examples on the main salary page, comparing 12 and 14 payments and showing what changes the net for the same gross. No new thin pages, just a better one that already ranks.
Closing
The pattern this week was finishing the last mile: TestFlight builds, a YouTube pipeline, a voice session tested on a real phone. Next up is publishing the first batch of journey videos, and seeing whether build-your-own onboarding moves that drop-off number.