Ingredients
Ingredients are the core building blocks of any Gram recipe.
Basic declaration
Section titled “Basic declaration”To declare an @ingredient, use the @ symbol. If the @ingredient name contains spaces or requires a specific quantity, you must append the quantity inside {} braces. If it is a single word without a specific quantity, the braces are optional (the quantity defaults to 1).
To specify a unit of measurement (weight, volume, etc.), add it directly after the numeric value inside the braces, separated by an optional space.
Scaling & fixed quantities
Section titled “Scaling & fixed quantities”By default, the Gram Compiler scales an @ingredient linearly based on the number of portions requested.
If you scale a recipe from 2 to 4 servings, an @ingredient with {100g} becomes {200g}.
Fixed quantities (=)
Section titled “Fixed quantities (=)”Some @ingredient items (like salt, yeast, or spices) should not scale linearly. You can lock their quantity using the = modifier.
This keeps the salt at 1 tsp regardless of how many servings the user calculates.
Ingredient modifiers
Section titled “Ingredient modifiers”Gram provides several modifiers to alter how an @ingredient behaves in the parser and the shopping list. Modifiers are placed immediately after the @ symbol.
| Modifier | Name | Effect |
|---|---|---|
& | Reference | References an @ingredient previously declared. Does NOT add it to the shopping list again. |
= | Fixed | Marks the quantity as fixed (it will not scale with portions). |
? | Optional | Marks the @ingredient as optional. |
- | Hidden | Hides the @ingredient from the generated shopping list. |
* | Baker’s % | Marks the @ingredient as the reference (100%) to calculate baker’s percentages. |
Optional and hidden modifiers (?, -)
Section titled “Optional and hidden modifiers (?, -)”Use ? to mark an @ingredient as optional — useful for garnishes or substitutions the cook may skip. Use - to hide an @ingredient from the generated shopping list entirely, e.g. something you always have on hand.
The reference modifier (&)
Section titled “The reference modifier (&)”The reference modifier is crucial for multi-step recipes. As a best practice, any time you mention an @ingredient after its initial declaration, you should use the & modifier.
The compiler’s behavior changes depending on whether you provide a new quantity with your reference:
- Pure Reference (No Quantity)
When instructing the user to use an already declared
@ingredient, use@&so it isn’t counted twice in the shopping list.
- Additive Reference (With Quantity)
Sometimes you need to use the same
@ingredientmultiple times with different additions throughout the recipe. Using@&ingredient{qty}tells the compiler: “This is the same@ingredient, please add this extra quantity to the total shopping list.”
Baker’s percentage (*)
Section titled “Baker’s percentage (*)”In baking, recipes are often built around the Baker’s Percentage, where the main @ingredient (usually flour) represents 100%, and all other items are expressed as a percentage of that weight.
Gram provides a dedicated modifier to mark the reference @ingredient. By placing a * after the @ symbol, you tell the Gram Compiler: “This is the 100% reference point”.
This allows tools (like the CLI or web renderers) to automatically calculate and display the baker’s percentages for all other items (e.g., Water: 70%, Salt: 2%) without you having to define them manually as relative quantities.
Advanced syntax
Section titled “Advanced syntax”Short-hand preparations
Section titled “Short-hand preparations”Often, an @ingredient requires preparation before use. You can define this directly within the declaration using parentheses ().
Component alias (renaming)
Section titled “Component alias (renaming)”You can rename an @ingredient for display purposes using a colon : immediately after the real name. This is useful for keeping the shopping list clean while using a colloquial name in the instructions.
Format: @Real Name:Display Name{Quantity}
The shopping list will aggregate this under “dry white wine”, but the rendered recipe will just say “wine”.
Alternatives (substitutions)
Section titled “Alternatives (substitutions)”You can define acceptable alternatives for an @ingredient using the pipe | operator.
This works with short-hand preparations as well:
Ranges
Section titled “Ranges”Recipes aren’t always exact. You can specify a range using a hyphen -.
Fractions
Section titled “Fractions”Quantities accept fractions in three forms — a plain fraction, a mixed number, or a Unicode fraction glyph — all normalized to the same decimal value.
Error handling
Section titled “Error handling”The compiler checks for semantic errors in your @ingredient declarations and will output specific warnings:
- Invalid Modifier: If you combine incompatible modifiers (like
?*), the compiler warnsINVALID_MODIFIER_COMBINATIONand ignores them. - Undefined Reference: If you use a reference (
@&ingredient) but that item hasn’t been declared previously in the recipe, the compiler warnsUNDEFINED_REFERENCE. - Database Missing: If you compile with a database and the
@ingredientis not found, it warnsMISSING_INGREDIENT. - Missing Macros: If the database lacks nutritional information for the
@ingredient, it warnsMISSING_MACROS. - Unknown Mass: If it cannot convert a volume or count into grams to estimate nutrition, it warns
UNKNOWN_MASS.