Artisan bread and pizza iOS app: details
I’m a big fan of Flour Water Salt Yeast, Ken Forkish’s epic book on fancy bread1.
Hence I’m writing a recipe app for fancy artisanal bread and pizza. For these loaves the ingredient calculations go a bit beyond bog standard bread2.
This sort of app/algorithm is a great example of when just “sit at keyboard and make it up as you go along” really doesn’t serve you at all. Properly planning the core algorithm up front is a big time-saver here!
If you want to flex your write app from scratch skills, or take a framework/architecture out for a spin, you could do much worse than writing a bread app. It’s not massively complicated, but it’s not too trivial either.
App features
- Can set the hydration and total recipe flour for making a certain bread type
- Can see total ingredients list as well as ingredients for each stage
- Given a recipe start time, view a typical timeline of when each stage is executed
- maybe: log when and what recipe was executed (with hydration used etc), and allow a note to be entered (how did the bake turn out?)
- maybe, baby: track an on-going recipe with timers, alerts
Networked features aren’t part of the main plan for this app; the first version will have a built-in recipe list. However, fetching a recipes list on-line (and locally caching of course) might be a nice way to allow updates without pushing a whole new app3.
The kinds of bread
The app needs to handle:
Straight dough
Flour, water, salt, (instant) yeast – mix, wait and fold.
Pre-ferments
Think Poolish (baguette bread) or Biga4: make a pre-ferment and leave overnight, mixing in with a final dough the next day.
Hybrid Levain
A live mother (starter) culture is refreshed then combined with a final dough that includes instant yeast.
Pure levain
Like hybrid, but no instant yeast is used.
Pizza
Technically bread, but with a roof made of yum.
The algorithm
To handle all of the above kinds of bread, we need have a recipe model that can:
- fill in placeholder water ingredient(s) with the correct amount of water to hit the overall recipe hydration
- handle set liquid ingredients: a literal amount of water (see Poolish and Biga pre-ferments)
- handle non-liquid ingredients that already have a hydration (useful for starter cultures in levains)
For convenience, the stored recipes will follow the baker’s recipe standard where they have a total of 1,000g of flour in it.
A few important equations
There’s a fundamental equation for combining two hydrated mixtures5 (e.g. a pre-ferment + final dough):
$$ h_+ = f . h_0 + h_1(1 - f) $$where \(h_0\), \(h_1\) are the hydrations of the two mixtures you’re combining, and \(f\) is the weight ratio of the two (\(w_0 / w_1\)).
In a non-trivial bread app you’ll need to re-arrange this to find \(h_1\) (for pre-ferments):
$$ h_1 = \frac{h_+ - f . h_0}{1 - f} $$Unit tests, you need them
If you implement something like this algorithm and don’t write unit tests, you are very silly.
The question of tweakable recipes
We could allow for recipes that let the user tweak the ‘design’ beyond hydration and total flour (“parameterised recipes”).
For example:
- Whole wheat loaf: let the user change the proportion of whole wheat flour to white flour
- Pre-ferment breads: let the user change the hydration of the pre-ferment (typically this is set to 100% hydration for Poolish, 68% for Biga)
Tweakable recipes might be overkill. Maybe users of this app wouldn’t care. It’s always worth asking yourself am I getting carried away here? I recommend being a bit ruthless in cutting excess fluff from your ideas! YAGNI applies to app features as well as code.
With that said, let’s look at how we’d do tweakable recipes. And if it did go in the app, it should be a feature that doesn’t clutter up the place – possibly an option that is by default hidden or out of the way.
Tweakable recipes sound handy, but varying something like the whole wheat proportion of a recipe has knock-on effects: typically you adjust your water, salt and yeast amounts accordingly.
So tweakable recipes would need us to supplement our recipe algorithm with relative hydration, salt, yeast. In this system recipes are specified like this:
- water, salt and yeast for a recipe are given as if it was a 100% white flour recipe
- relative hydration, salt, and yeast6 adjustments are known for any non-white flours in the recipe; we apply them according to the flour’s percentage of the total flour in recipe
If the algorithm did implement tweakable recipes, we’ll have to change our app recipe list into tweakable form, i.e. water salt yeast amounts are given as if every recipe is 100% white flour, and are fixed-up in the algorithm using the relative measures.
there’s a post coming soon on my experiences of using the FWSY method. Forkish also has an excellent book Elements of Pizza; I’d disregard the pizza bits at end of FWSY book and get the EoP book, if you’re interested ↩︎
don’t get me wrong, it’s not crazily complicated, it just requires some thought ↩︎
probably be fine to host the recipe json in cloudflare, where this blog is hosted, traffic allowing. But from a different worker, for separation of concerns ↩︎
the Biga recipe has a mistake you can easily make7, which is instantly game over loaf, which is why I want the app to show reminders or even an alert for this sort of thing ↩︎
this is just the general equation for weighted combination of two ratios; hydration is just a ratio, after all ↩︎
relative measures are given as the percentage increase required of e.g. water if the entire recipe was made of that flour; e.g. 0% means no change, 3% would be an increase in the ingredient, -5% a decrease. White flour has relative measures of 0% across the board because it’s the reference point ↩︎
the mistake is to mix the next-day flour directly into the pre-ferment – it clumps disastrously due to the very low hydration, and you can’t undo this ↩︎