Skip to content

Importing recipes

Press Import on the Recipes page. Three kinds of file are accepted, and the format is decided by looking inside the file rather than at its extension:

  • BeerXML — what BeerSmith, Brewfather and Brewer’s Friend all export
  • BeerJSON — the newer format, from anywhere
  • A Beerwright data export — your own workspace export

Nothing is uploaded. A two-hundred-recipe file is read, parsed, matched against the ingredient catalog and fully costed without a byte leaving the tab.

  1. Choose a file. A picker, not a drop zone.
  2. Preview. Every recipe in the file, pre-ticked and individually toggleable, with its vitals computed by Beerwright’s own engine shown alongside what the file claimed — 1.062 next to (file: 1.060). A difference there is not a bug; it usually means the two tools disagree about IBU model or efficiency, and the preview is deliberately not allowed to quote the file’s numbers back at you for a better first impression.
  3. Confirm. Each selected recipe arrives as one action, so ⌘Z undoes one recipe. The first one opens.

Beside each recipe the preview says how the ingredients landed — “8 matched”, “2 custom” — and a collapsed panel lists any notes and warnings.

If the file is malformed you get the parser’s own message, with the line and column, and nothing is imported.

A catalog match supplies identity and unpublished chemistry. The file supplies every number it stated.

So if your BeerXML says Maris Otter at 37 PPG and 3 °L, you get Maris Otter at 37 PPG and 3 °L — your numbers, not the catalog’s. The catalog fills in only what the file could not say.

There is exactly one exception, and it is the reason matching matters at all: mash-pH chemistry. Distilled-water pH, buffering capacity and malt class cannot be expressed in either format. A catalog match is the only way to get them, and a miss leaves them empty rather than inventing a plausible number.

Names are matched by token similarity against roughly five hundred catalog entries — accent-folded, plurals stemmed, noise words like malt, pellet and hops dropped, region qualifiers ignored. Yeast product codes (US-05, WLP001) match outright.

Two things stop a match dead:

  • A family or form disagreement. A sugar never matches a grain; a dry yeast never matches a liquid strain.
  • A number disagreement. Crystal Malt - 20L scores zero against Crystal 60. Names that differ only in a number are different ingredients, and a 40 °L colour error is a visibly wrong beer.

A miss is an ordinary outcome, not a failure. The ingredient is built from the file’s own values and calculates identically; it is simply marked as custom, and the import notes say so.

BeerXML is a 2008 format and the tools that write it disagree. Where Beerwright has to make a judgement, it makes it and then tells you in the import notes.

The file says Beerwright reads it as Why
USE=Aroma A whirlpool addition, with the stated time as the stand The alternative — a zero-minute boil addition — throws away every IBU a modern hoppy recipe gets from its whirlpool
RECOMMEND_MASH=FALSE on a base malt Ignored; the recipe’s own type decides mash or steep BeerSmith writes this on base malts. Honouring it costs an all-grain recipe a third of its gravity
A dry-hop time over 60 Minutes BeerSmith writes minutes
A dry-hop time of 60 or less Days Brewfather writes days
A yeast amount by weight 11.5 g sachets
A yeast amount of 0.5–10 L Packs
Any other yeast volume 35 mL vials
A style category number Used only if the file names the 2021 guidelines 2008’s 8B is Special Bitter; 2021’s 8B is Schwarzbier. A number from the wrong edition is worse than no style

Where the file says nothing at all, a documented default is used and announced: 66 °C for 60 minutes if there is no mash step, 20 °C for 14 days if there is no fermentation schedule, 18.927 L (5 US gal) if there is no batch size, 60 minutes of boil, 75 % attenuation, 2.4 volumes of CO₂.

Values that are merely out of range are clamped and announced. Values that are impossible — 250 % attenuation, pH 14 — are ignored rather than clamped into a lie.

  • Every DISPLAY_* field. Beerwright never reads one; the numeric field beside it is the truth.
  • Tasting notes and ratings, the file’s own style ranges, priming and keg fields, and unknown vendor tags.
  • Per-ingredient notes. The recipe’s notes survive, prefixed with the brewer’s name where the file gave one.
  • BeerJSON’s equipment block.
  • A unit nobody recognises. This is the important one: an unrecognised unit reads as “not stated”, never as the bare number with the unit ignored. A gravity in Plato or Brix is refused at the boundary for the same reason.

There is also a per-recipe ceiling — 64 fermentables, 64 hops, 64 miscellaneous items, 16 yeasts, 16 mash steps, 16 fermentation steps.

Brewfather, BeerSmith and Brewer’s Friend

Section titled “Brewfather, BeerSmith and Brewer’s Friend”

There is no Brewfather integration, no account linking and no API. Those tools are supported through the files they export, and the quirks named in the table above are exactly the quirks their exports have. Export BeerXML or BeerJSON from them, import it here.

Your recipes must not change when the ingredient catalog is updated. So when an ingredient matches, Beerwright copies the fields the engine calculates with — yield, colour, moisture, alpha acid, attenuation, the mash-pH chemistry — into the recipe document itself.

Each item also carries a provenance stamp: which catalog entry it matched, and the catalog version at the moment of the match, like 2026.08.0. That stamp is provenance and nothing more. Nothing in the engine ever follows it to re-read a value. A recipe imported today calculates the same way in a year, whatever has happened to the catalog since.

What is not kept is the original file. Beerwright does not store the bytes you imported, and there is no “view original” anywhere. The parsed recipe is the record.

The vitals the file claimed are shown in the preview and then discarded — they are never used in a calculation and never written into the recipe.

Two ways out:

  • A single recipe — the recipe’s overflow menu, Export as BeerJSON. The computed vitals are written into the file.
  • Everything — Settings, Export all data, giving beerwright-workspace-YYYY-MM-DD.json with recipes, equipment profiles, water profiles and settings.

There is no BeerXML export. BeerXML is read, not written; BeerJSON is the format out.

A Beerwright BeerJSON export carries an extension block with the ingredient snapshots, the provenance stamps and the water section, so re-importing your own export restores the recipe exactly. Other programs ignore that block and read the standard BeerJSON around it.

Importing a workspace export brings in recipes only — equipment profiles, water profiles and settings are in the file but this path does not read them, and the import notes say so.

The dialog knows your recipe count and warns before you start:

Your plan has room for 3 more recipes. Importing more than that will import the first 3 and leave the rest — deselect some, or upgrade first.

It does not block you. The cap is enforced by the server when each recipe is applied, so the first few land and the rest are declined. See Plans, billing and trial codes.