House Formulation Doctrine

How a recipe gets designed here — the ratios that have worked, why they work, and the rails a new formula stays inside. This is what formulate reasons from. It is taste plus six batches of evidence, not chemistry law; a departure is allowed, but it's a decision, not a default.

The backbone is Bastille — a soap that is mostly olive oil (a true Castile is 100% olive). Olive makes a mild, conditioning, hard-when-cured bar that's gentle enough for daily use. The rest of the formula is small levers on top of that.

The two house blends

Everything to date is one of these two, and they cover the whole use-case range so far.

Body bar — 72 / 18 / 10 at 5% superfat

Olive 72% / coconut 18% / castor 10%. The default for a bar that isn't washing hands ten times a day. High olive for mildness, 18% coconut for enough lather and cleansing without stripping, 10% castor for creamy bubbles. Batches #1–#4.

Hand bar — 62 / 28 / 10 at 6% superfat

Olive 62% / coconut 28% / castor 10%, superfat bumped to 6%. A frequently-used hand bar needs more cleansing and a bubblier lather, which is the 28% coconut — but 28% coconut alone would start to dry skin, so the extra superfat cushions it back. The two moves are a pair; don't make one without the other. Batches #5–#6.

The levers, and their rails

Fragrance

Load rates, all as a percentage of oil weight, from what's actually been poured:

formulate pulls the real per-oil data from inventory/fragrances.toml. Three things there change a design:

How formulate uses this

  1. Mold + use case → blend and superfat. Hand-washing picks the hand bar; a body/shower bar picks the body bar. A new use case is a real design conversation, not a default.
  2. Mold + target fill → oil weight, via tools/lye.py --fit. Aim for ~92–95% of a mold's ceiling — full bars, real margin against overflow. Never design to 100%.
  3. Fragrance choice → check the ledger for amount, vanillin, and behavior; set the load rate to taste and to what the bottle holds.
  4. Everything → tools/lye.py for the actual weights, fill, and yield. Never by hand.
  5. Brian cross-checks on SoapCalc. Only then is it Ready.

Room to grow

Directions the palette could take, noted so they're on the radar — none tried yet, each a real design conversation when it comes up: