Importing ingredients
The ingredients import turns a stock spreadsheet into ingredient records in one pass. It is usually the first import you run. The upload, mapping and per-row checks work the same for every import kind; see CSV imports for that flow.
Columns
Section titled “Columns”| Field | Required | What goes in it |
|---|---|---|
| Name | Yes | The ingredient’s name, e.g. “Habanero, fresh” |
| Unit | Yes | The unit it is measured in: g, kg, ml, L, units |
| Density | No | Grams per millilitre, for volume-to-mass conversions |
| Category | No | The name of one of your categories |
| Opening stock | No | Quantity on hand, in the ingredient’s own unit |
| Unit cost | No | What one unit costs, used to seed the average cost |
Common header names map on their own: “uom” finds Unit, “famille” finds Category. Anything else you match by hand under Column mapping.
Variants
Section titled “Variants”With ingredient variants on your plan, the same file carries an ingredient’s variants and what they are made from (one ingredient, several variants). The ingredients export writes these eleven columns in this order, so a file exported from one workspace comes back into another as the same groups and links.
| Field | What goes in it |
|---|---|
| variant_of | The ingredient this row is a variant of: “Cherries” on the row named “Cherries · Pitted” |
| variant | The variant’s label: “Pitted”. Blank on the ingredient’s own row |
| made_from | The label of the variant this one is made from. Blank means the ingredient itself |
| gives_per_100 | Grams of this variant that 100 g of the source gives: 88 |
| gives_low, gives_high | The range a lot falls in, both or neither: 85 and 92 |
| operation | What the making is called: “Pitting” |
| setup_minutes | Minutes to set up, whatever the quantity |
| minutes_per_unit | Minutes per unit of the source: 0.008 per gram is 8 minutes per kilo |
| interchangeable | yes or no: whether a batch may take this variant when a sibling is short |
| sourcing | bought or made: which price and which first move a batch reads |
Name is still the full name, “Cherries · Pitted”. A row with a label joins the ingredient variant_of names, wherever that ingredient is: already in your inventory, earlier in the file, or later in it. A variant_of nothing is called yet creates that plain ingredient first, in the row’s unit and category, and the row joins it. The link is written last, once every variant of the ingredient is in, so made_from can name a sibling further down the file.
A label without variant_of, a yield that is not a number above zero, or a sourcing word other than bought or made holds the row back. What cannot be settled after the ingredient is created (a label already taken, a source that names no variant, a range that does not sit around its figure) does not: the ingredient imports, and the row says what was left for you to finish on its page.
Without ingredient variants on your plan, the eleven columns are read past. Each row that carried one imports as a plain ingredient and says so.
Categories and other details
Section titled “Categories and other details”The category cell is matched by name against categories you already created. A cell that matches nothing leaves the ingredient uncategorized, so set up your categories before a large import.
Compliance details (allergens, INCI fields, shelf life) and category custom fields are not import columns. Fill them in on each ingredient’s card afterwards, or let AI enrichment suggest the compliance values.
Opening stock
Section titled “Opening stock”Tick Also set opening stock and the quantity column is posted as each new ingredient’s opening balance, in its own unit. Provide a unit cost too and it seeds the weighted average cost, so recipes cost correctly from day one. A hot-sauce row might read: name “Habanero, fresh”, unit kg, category “Chilis”, opening stock 12, unit cost 8.40.
Opening stock only posts for ingredients the import creates. Re-running the same file never double-counts stock.
Duplicates
Section titled “Duplicates”Ingredient names are unique. A row whose name already exists in your inventory is flagged “An ingredient with this name already exists” and held back; the import never silently creates a second record for the same thing. Rows that repeat inside the file are flagged as duplicates too, so a messy export cannot import the same line twice.