{
  "id": "com.lattice.recipes",
  "name": "Recipes",
  "icon": "🍲",
  "color": "#b65d35",
  "description": "Save ingredients, instructions and cooking times in schema.org Recipe format.",
  "provenance": "Schema.org Recipe, verified 2026-10-14: https://schema.org/Recipe . Adopted name, description, url, author (Text), datePublished -> date_published, prepTime -> prep_time, cookTime -> cook_time, totalTime -> total_time, recipeYield -> recipe_yield, recipeCategory -> recipe_category, recipeCuisine -> recipe_cuisine, recipeIngredient -> recipe_ingredient, recipeInstructions -> recipe_instructions. Repeated Text ingredients use JSON array text; author, yield and instructions select supported Text forms, excluding structured alternatives. Times remain ISO 8601 durations and yield remains text. id is a local surrogate. This is the public Recipe interchange vocabulary, not a claim about any proprietary recipe app export. Local events/listeners are fixture actions.",
  "requested_permissions": {
    "storage": [
      "sql"
    ],
    "network": {
      "allowlist": []
    },
    "events": {
      "recipe-saved": {
        "description": "A recipe was saved.",
        "schema": {
          "type": "object",
          "properties": {
            "id": {
              "type": "integer",
              "description": "Recipe ID."
            },
            "name": {
              "type": "string",
              "description": "Recipe name."
            },
            "description": {
              "type": [
                "string",
                "null"
              ],
              "description": "Recipe description; null means unspecified."
            },
            "url": {
              "type": [
                "string",
                "null"
              ],
              "description": "Original recipe URL; null means unspecified."
            },
            "author": {
              "type": [
                "string",
                "null"
              ],
              "description": "Author name as text; null means unspecified."
            },
            "date_published": {
              "type": [
                "string",
                "null"
              ],
              "description": "Publication date, YYYY-MM-DD; null means unspecified.",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "prep_time": {
              "type": [
                "string",
                "null"
              ],
              "description": "Preparation time, ISO 8601 duration, e.g. PT15M; null means unspecified."
            },
            "cook_time": {
              "type": [
                "string",
                "null"
              ],
              "description": "Cooking time, ISO 8601 duration, e.g. PT1H; null means unspecified."
            },
            "total_time": {
              "type": [
                "string",
                "null"
              ],
              "description": "Total time, ISO 8601 duration, e.g. PT1H15M; null means unspecified."
            },
            "recipe_yield": {
              "type": [
                "string",
                "null"
              ],
              "description": "Yield text, e.g. 1 loaf or 4 servings; null means unspecified."
            },
            "recipe_category": {
              "type": [
                "string",
                "null"
              ],
              "description": "Recipe category, e.g. dessert; null means unspecified."
            },
            "recipe_cuisine": {
              "type": [
                "string",
                "null"
              ],
              "description": "Cuisine, e.g. French; null means unspecified."
            },
            "recipe_ingredient": {
              "type": "string",
              "description": "JSON-encoded array of ingredient strings with quantities and units; [] means none.",
              "contentMediaType": "application/json"
            },
            "recipe_instructions": {
              "type": [
                "string",
                "null"
              ],
              "description": "Instructions as prose text; null means unspecified."
            }
          },
          "required": [
            "id",
            "name"
          ],
          "additionalProperties": false
        }
      },
      "recipe-updated": {
        "description": "A recipe was updated.",
        "schema": {
          "type": "object",
          "properties": {
            "id": {
              "type": "integer",
              "description": "Recipe ID."
            },
            "name": {
              "type": "string",
              "description": "Recipe name."
            },
            "description": {
              "type": [
                "string",
                "null"
              ],
              "description": "Recipe description; null means unspecified."
            },
            "url": {
              "type": [
                "string",
                "null"
              ],
              "description": "Original recipe URL; null means unspecified."
            },
            "author": {
              "type": [
                "string",
                "null"
              ],
              "description": "Author name as text; null means unspecified."
            },
            "date_published": {
              "type": [
                "string",
                "null"
              ],
              "description": "Publication date, YYYY-MM-DD; null means unspecified.",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "prep_time": {
              "type": [
                "string",
                "null"
              ],
              "description": "Preparation time, ISO 8601 duration, e.g. PT15M; null means unspecified."
            },
            "cook_time": {
              "type": [
                "string",
                "null"
              ],
              "description": "Cooking time, ISO 8601 duration, e.g. PT1H; null means unspecified."
            },
            "total_time": {
              "type": [
                "string",
                "null"
              ],
              "description": "Total time, ISO 8601 duration, e.g. PT1H15M; null means unspecified."
            },
            "recipe_yield": {
              "type": [
                "string",
                "null"
              ],
              "description": "Yield text, e.g. 1 loaf or 4 servings; null means unspecified."
            },
            "recipe_category": {
              "type": [
                "string",
                "null"
              ],
              "description": "Recipe category, e.g. dessert; null means unspecified."
            },
            "recipe_cuisine": {
              "type": [
                "string",
                "null"
              ],
              "description": "Cuisine, e.g. French; null means unspecified."
            },
            "recipe_ingredient": {
              "type": "string",
              "description": "JSON-encoded array of ingredient strings with quantities and units; [] means none.",
              "contentMediaType": "application/json"
            },
            "recipe_instructions": {
              "type": [
                "string",
                "null"
              ],
              "description": "Instructions as prose text; null means unspecified."
            }
          },
          "required": [
            "id",
            "name"
          ],
          "additionalProperties": false
        }
      },
      "recipe-removed": {
        "description": "A recipe was removed.",
        "schema": {
          "type": "object",
          "properties": {
            "id": {
              "type": "integer",
              "description": "Recipe ID."
            },
            "name": {
              "type": "string",
              "description": "Recipe name."
            },
            "url": {
              "type": [
                "string",
                "null"
              ],
              "description": "Original recipe URL; null means unspecified."
            }
          },
          "required": [
            "id",
            "name"
          ],
          "additionalProperties": false
        }
      }
    },
    "listeners": {
      "save-recipe": {
        "description": "Save a recipe.",
        "schema": {
          "type": "object",
          "properties": {
            "id": {
              "type": "integer",
              "description": "Recipe ID; generated when omitted."
            },
            "name": {
              "type": "string",
              "description": "Recipe name."
            },
            "description": {
              "type": [
                "string",
                "null"
              ],
              "description": "Recipe description; omitted or null means unspecified."
            },
            "url": {
              "type": [
                "string",
                "null"
              ],
              "description": "Original recipe URL; omitted or null means unspecified."
            },
            "author": {
              "type": [
                "string",
                "null"
              ],
              "description": "Author name as text; omitted or null means unspecified."
            },
            "date_published": {
              "type": [
                "string",
                "null"
              ],
              "description": "Publication date, YYYY-MM-DD; omitted or null means unspecified.",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "prep_time": {
              "type": [
                "string",
                "null"
              ],
              "description": "Preparation time, ISO 8601 duration, e.g. PT15M; omitted or null means unspecified."
            },
            "cook_time": {
              "type": [
                "string",
                "null"
              ],
              "description": "Cooking time, ISO 8601 duration, e.g. PT1H; omitted or null means unspecified."
            },
            "total_time": {
              "type": [
                "string",
                "null"
              ],
              "description": "Total time, ISO 8601 duration, e.g. PT1H15M; omitted or null means unspecified."
            },
            "recipe_yield": {
              "type": [
                "string",
                "null"
              ],
              "description": "Yield text, e.g. 1 loaf or 4 servings; omitted or null means unspecified."
            },
            "recipe_category": {
              "type": [
                "string",
                "null"
              ],
              "description": "Recipe category, e.g. dessert; omitted or null means unspecified."
            },
            "recipe_cuisine": {
              "type": [
                "string",
                "null"
              ],
              "description": "Cuisine, e.g. French; omitted or null means unspecified."
            },
            "recipe_ingredient": {
              "type": "string",
              "description": "JSON-encoded array of ingredient strings with quantities and units; omitted defaults to \"[]\".",
              "contentMediaType": "application/json"
            },
            "recipe_instructions": {
              "type": [
                "string",
                "null"
              ],
              "description": "Instructions as prose text; omitted or null means unspecified."
            }
          },
          "required": [
            "name"
          ],
          "additionalProperties": false
        }
      }
    }
  },
  "x-effects": {
    "save-recipe": {
      "table": "recipes",
      "emits": "recipe-saved"
    }
  },
  "source": {
    "assets": [
      "index.html",
      "app.js",
      "app.css",
      "ui.css",
      "emits.js",
      "listens.js"
    ]
  }
}