Native apps
Shipped iOS work — SwiftUI, widgets, watchOS, StoreKit.
Not a React Native shell. Pencil input, offline databases, App Store review, and the boring release machinery that keeps an app alive after launch day.
Handwriting that becomes text and live sessions that become notes; AI answers grounded in the Rules of Golf, with an offline database when the signal drops.
Case studies
Long-form writeups of how the work actually went.
2026–Endeo
Handwriting on an iPad, turned into searchable text — and a sermon, transcribed while you take notes on it.
2026–RuleCaddie
A golf rules assistant that cites the rule it's answering from, and still answers when the course has no signal.
2026–Veto
Everyone secretly vetoes what they won't tolerate — and the database, not the app, is what keeps those vetoes secret.
2026–Private Reserve
A palate log that has to survive a dark, loud bar — and private club rooms where the verdicts get argued out.
Selected work
- EndeoiPad-first Bible study app. Handwrite notes on any passage with Apple Pencil and have them turned into text; record a teaching session and get it transcribed, linked to your notes, and summarized.Case study →
- RuleCaddieGolf rules answered on the course — AI chat grounded in the official R&A/USGA Rules of Golf, with an offline rules database when there's no signal, plus a watch app and widget.Case study →
- VetoGroup decisions, settled. Everyone secretly vetoes what they won't tolerate and the app reveals what survived — vetoes stay private by design, with the winner computed server-side.Case study →
- Private ReserveA palate log for spirits, with private club rooms where a group logs the pours going around and argues the verdicts.Case study →
Field notes
- A widget extension is not the writerA Home Screen button can look like it writes in the widget. Put the write in the main app, give the extension read-only access, and pin the intent with ExecutionTargets.
- A curated walkthrough is not evidenceA polished happy path persuades a room. It does not answer the question you wrote down. Match the evidence to the claim, or you are running a demo under a prototype label.
- A debounce is not a latency budgetDelaying OCR and saves keeps the canvas from stuttering under load. It does not make the ink follow the tip. Treat stroke latency as its own budget.
- A crash-free rate is not a ship gateA green crash-free session percentage can hide missing dSYMs, hang-only failures, and short TestFlight sessions. Treat the rate as a signal, not the release decision.
- A higher fidelity is not a better answerPaper, Figma, and a coded slice answer different risks. Climbing the fidelity ladder because the last artifact looked unfinished is how teams polish the wrong question.
- A wizard behind the curtain is not a coded probeA human simulating the system can prove the interaction lands. It cannot prove the model, the database, or the offline path will hold. Use the wizard for mental models; use a coded probe for the seam that can fail.
- A fake door is not a prototypeA painted button measures curiosity. A prototype measures whether the hard part holds. Confusing the two is how teams greenlight a build on a click rate.
- An Accessibility Inspector pass is not a VoiceOver testXcode's audit catches missing labels. It does not prove a common task works with VoiceOver on glass — or that Screen Recognition is not covering for you.