Skip to content

Document structure

A Gram recipe file (.gram) is structured into several distinct parts: Metadata, Sections, Steps, and Comments.

The frontmatter is a YAML block at the very start of the file, enclosed by ---.

The Gram parser accepts any key-value pair in this block. You can add custom fields for your own application’s needs. However, the Gram Compiler recognizes two types of keys: Functional and Informational.

These keys directly alter how the Gram Compiler processes the recipe:

  • portions: (Integer) The baseline number of servings. Divides the Nutritional Estimation into per-portion figures, and is rescaled alongside quantities when a recipe is scaled — so per-portion values stay the same whatever factor you apply. A trailing label (portions: 4 servings) is tolerated; a zero or negative count is ignored.
  • densities: (Object) Custom density overrides for specific @ingredient items, used by the Mass Standardization algorithm.

These keys are recommended for proper display and metadata management:

  • title: The recipe name.
  • description: A short summary (useful for SEO meta tags).
  • tags: A list of categories or keywords.
  • category: Main category (e.g. “Dessert”, “Main Course”).
  • author: Name or list of authors.
  • source: URL(s) to the original recipe.
  • date, lastUpdated: YYYY-MM-DD.
  • makes: The physical output or dimensions of the recipe (e.g., “1 layer cake”, “24 cookies”, “20x20cm mold”).
  • notes: General notes about the recipe (e.g. “Tested on 2026-06-07. Decrease sugar next time.”).
---
title: 'Matcha Brownies'
description: 'A simple Japanese-style matcha brownie...'
author: ["Auguste Kerflec"]
tags: ['brownie', 'matcha']
category: 'Dessert'
source: ['https://example.com/matcha-brownie']
makes: '20x20cm mold'

# Functional Fields
portions: 4
densities:
  - flour: 0.55
---
v1.2.0

Right after the frontmatter, before any step, a recipe can @use other .gram files as reusable sub-components.

@use "./bases/pate-sablee.gram" as &pate

## Montage

[Foncer] le moule avec &pate{250g}.

See Module Imports for the full syntax, scaling rules, and encapsulation guarantees.

Each paragraph in a Gram file represents a single cooking step. Steps are separated by one or more empty lines.

A step,
the same step.

A different step.

Steps can optionally start with an Action enclosed in brackets []. This highlights the primary method used in that step, making it easy to parse visually or programmatically.

[Mix] The @flour and @water.

[Bake] In the #oven for ~{30min}.

Complex recipes often have multiple components (e.g., dough, filling, frosting) that are prepared separately. You can group steps into ## Section blocks using Markdown-style headings (e.g., ## Dough).

## Dough

Mix @flour{200g} and @water{100ml} together until smooth.

## Filling

Combine @cheese{100g} and @spinach{50g}, then season to taste.

You can assign a preparation timeframe to a ## Section by adding a ~timer-like annotation anywhere in the title.

## Puff Pastry ~{-2d}

This tells the compiler that the “Puff Pastry” ## Section should be prepared 2 days in advance. Supported suffixes are d (days), h (hours), min or m (minutes) — free text (e.g. ~{the day before}) is not valid here and is flagged by the compiler.

See Times & Scheduling for the full syntax rules and error handling.

If a ## Section produces a sub-component that will be used later in the recipe, you can declare it using ->& at the end of the title.

## Puff Pastry ->&dough

See Intermediate Variables for more details.

You can add comments to explain instructions without affecting the compiled output.

Inline Comments (//):

Mash @potato{2kg} until smooth // alternatively, boil 'em first.

Block Comments (/* ... */):

Slowly add @milk{4 cup} /* TODO change units to litres */, keep mixing.