You're in the grocery store, and by the produce section your phone is down to one bar. You open your meal plan to check whether it was one onion or two. The app shows a spinner. You buy three onions.
The first version of Porks worked like most apps: your recipes lived on my server, and the app had to ask for them. That's fine until the signal drops in the cereal aisle, which it always does.
The Cache That Became the App
Last year I built a caching system so Porks would keep working when service was spotty. Every recipe, meal, grocery list and pantry item got a local copy in SwiftData. Changes you made offline went into a queue and replayed once you had signal again. A small status toast in the toolbar reports Offline, Syncing… or 3 changes pending, so you always know where things stand.
Somewhere along the way, I noticed the app was already reading almost everything from the device. The server had become a backup that also checked your ID at the door.
Porks 2.0
So the next goal was to drop the account.
Porks 2.0 is local-first. Open it and you go straight into the app. Recipes, meals, the calendar and grocery lists all work fully offline, with no account required. You only need one for the features that are actually about other people: sharing a home, searching public recipes and user profiles.
The idea is that, as much as is feasibly possible, you own your recipes, and you don't need my server to keep using them. The fancy name is local-first, from Ink & Switch's essay Local-first software. If you build apps, read it. The plain name is "the notebook in the kitchen drawer," which also never asked for a password.
The Rest of the Summer
Removing the login screen took an afternoon. Everything that assumed someone was signed in took the rest of the summer.
- Sync had to leave the main thread. It now runs in a background actor that reports back only what changed, so the calendar doesn't stall while your library updates.
- Recurring meals kept vanishing. The server sends a repeating dinner as a series of single dates, not the rule behind them, so a partial sync could delete a series from the device with nothing left to rebuild it from. Now any change that touches a recurring series triggers a full pass.
- Signing in can't erase anything. Use Porks without an account for six months, then sign up, and your library goes up to the new account instead of being wiped.
- Neither can signing out. Moving a meal plan into a different account means rebuilding every link between meals and recipes along the way. Without that, a weekly Taco Tuesday shows up as fifty separate Tuesdays. Now it shows up as one.
- The Watch needed a new path. Without an account, the iPhone sends the Watch a snapshot of your upcoming meals and grocery list, and grocery edits from your wrist get sent back.
None of it is glamorous, and all of it had to work before I could remove a single button. Porks now opens quickly, works in the grocery store and doesn't need anything from you first.
What's Next
Right now, a local-only library lives on one device. The next step is iCloud sync for people without an account, so your recipes follow you from iPhone to iPad to Mac without my server ever holding them.
After that, I've been exploring ATProto. It would make Porks more social and let you self-host your recipes: you could share a cookbook with friends while the recipes stay on a server you control. I wrote more about why that matters in Atmosphere.
In the meantime, the list loads in the produce section on one bar or none.
You buy two onions now.
Discussion
View on Bluesky →No comments yet.