diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..7c5096f
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,9 @@
+.git
+.astro
+dist
+generated
+node_modules
+var
+.env*
+*.png
+*.html
diff --git a/.gitea/workflows/build-and-push-image.yaml b/.gitea/workflows/build-and-push-image.yaml
index 44ee080..086408a 100644
--- a/.gitea/workflows/build-and-push-image.yaml
+++ b/.gitea/workflows/build-and-push-image.yaml
@@ -1,4 +1,4 @@
-name: Build & Push Astro Site Image
+name: Build & Deploy Formulation
on:
push:
@@ -12,7 +12,7 @@ jobs:
env:
REGISTRY_USERNAME: nicholas
IMAGE_REGISTRY: git.uuard.com
- IMAGE_NAME: nicholas/recipe-book
+ IMAGE_NAME: nicholas/formulation
IMAGE_TAG: ${{ github.sha }}
runs-on: shared-ci
steps:
@@ -27,13 +27,9 @@ jobs:
- name: ✅ Validate recipe data
run: |
- python3 -m pip install --user -r requirements-dev.txt
- scripts/validate-content
-
- - name: 🏗️ Build Astro site
- run: |
- npm ci
- npm run build
+ python3 -m venv .venv
+ .venv/bin/pip install -r requirements-dev.txt
+ .venv/bin/python scripts/validate-content
- name: 🔐 Gitea Registry Login
uses: docker/login-action@v3
@@ -83,11 +79,11 @@ jobs:
chmod 600 ~/.kube/config
kubectl auth can-i update deployments --namespace nicholas
- - name: Deploy recipe-book
+ - name: Deploy Formulation read-only viewer
run: |
set -euo pipefail
- sed -E -i "s#newTag: [0-9a-f]+#newTag: ${IMAGE_TAG}#" k8s/kustomization.yaml
- grep -q "newTag: ${IMAGE_TAG}$" k8s/kustomization.yaml
+ sed -E -i "s#newTag: \"[0-9a-f]+\"#newTag: \"${IMAGE_TAG}\"#" k8s/kustomization.yaml
+ grep -q "newTag: \"${IMAGE_TAG}\"$" k8s/kustomization.yaml
kubectl apply --kustomize k8s
if ! kubectl rollout status deployment/recipe-book \
--namespace nicholas --timeout=180s; then
diff --git a/Dockerfile b/Dockerfile
index dfeee3c..685d53e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,7 +1,23 @@
-FROM nginx:alpine
+FROM node:24-alpine AS build
-RUN rm -rf /usr/share/nginx/html/*
+WORKDIR /app
+COPY package.json package-lock.json ./
+RUN npm ci
+COPY . .
+RUN npm run db:reset && npm run build
-COPY dist /usr/share/nginx/html/
+FROM node:24-alpine AS runtime
-EXPOSE 80
+ENV NODE_ENV=production \
+ FORMULATION_READ_ONLY=true \
+ HOST=0.0.0.0 \
+ PORT=8080
+WORKDIR /app
+COPY package.json package-lock.json ./
+RUN npm ci --omit=dev
+COPY --from=build --chown=node:node /app/dist/app ./dist/app
+COPY --from=build --chown=node:node /app/var/recipe-book.sqlite ./var/recipe-book.sqlite
+COPY --from=build --chown=node:node /app/public ./public
+USER node
+EXPOSE 8080
+CMD ["node", "dist/app/server/entry.mjs"]
diff --git a/README.md b/README.md
index 6893724..f780514 100644
--- a/README.md
+++ b/README.md
@@ -5,11 +5,10 @@ costing, and analyzing professional recipes. It models ingredients and
sub-recipes as reusable entities instead of embedding duplicated ingredient
data in every recipe.
-The project includes two independent Astro applications:
-
-- A SQLite-backed management application for recipes, ingredients, purchasing,
- nutrition, costs, preparation actions, conversions, and recipe books.
-- A read-only static cooking site generated from the same culinary data.
+The Astro application can run as either the full editor or a server-enforced
+read-only viewer. Both modes provide recipes, ingredients, purchasing data,
+nutrition, live costs, scaling, conversions, and recipe books. Read-only mode
+removes persistent editing while retaining browser-side calculations.
## Capabilities
@@ -42,8 +41,8 @@ python3 -m pip install --user -r requirements-dev.txt
## Database
SQLite is the canonical writable store. The database is located at
-`var/recipe-book.sqlite` and is intentionally excluded from Git. Numbered SQL
-migrations in `migrations/` define its schema.
+`var/recipe-book.sqlite` and is intentionally excluded from Git. The single
+baseline in `migrations/001_initial.sql` defines its complete schema.
Create a new local database from the portable culinary dataset:
@@ -51,22 +50,15 @@ Create a new local database from the portable culinary dataset:
npm run db:reset
```
-This command replaces an existing local database. For an existing database,
-apply pending migrations without replacing data:
-
-```bash
-npm run db:migrate
-```
-
-`npm run db:sync` is an alias for the safe migration command. YAML under
-`culinary/` is retained as portable seed and interchange data; normal edits in
-the management application write to SQLite.
+This command replaces an existing local database. There is intentionally no
+legacy upgrade chain. YAML under `culinary/` is retained as portable seed and
+interchange data; normal edits in the management application write to SQLite.
See [Local application](docs/local-application.md) for more detail.
## Development
-Run the management application:
+Run the editor:
```bash
npm run dev:app
@@ -81,18 +73,18 @@ development server:
npm run restart:app
```
-Run the static cooking site separately:
+Run the same application in read-only mode:
```bash
-npm run dev:site
+npm run dev:readonly
```
-Open . The site command creates a read-only projection
-at `generated/site-projection.json` before Astro starts.
+Open . The database is opened read-only, modifying
+HTTP requests are rejected, and editing controls and routes are unavailable.
## Validation and builds
-Run application and site type checks, unit tests, and both production builds:
+Run type checks, unit tests, and the production build:
```bash
npm run check
@@ -100,10 +92,8 @@ npm test
npm run build
```
-Build output is separated by application:
-
-- `dist/app/` — standalone Node server for the management application
-- `dist/site/` — static public cooking site
+The standalone Node server is written to `dist/app/`. Start a production
+read-only instance on port 4399 with `npm run start:readonly`.
## Culinary data tools
diff --git a/astro.config.mjs b/astro.config.mjs
deleted file mode 100644
index 38dcc06..0000000
--- a/astro.config.mjs
+++ /dev/null
@@ -1,14 +0,0 @@
-import { defineConfig } from "astro/config";
-import preact from "@astrojs/preact";
-
-export default defineConfig({
- site: "https://recipes.uuard.com",
- output: "static",
- srcDir: "./src/site",
- publicDir: "./public",
- outDir: "./dist/site",
- integrations: [preact()],
- vite: {
- server: { fs: { allow: ["."] } },
- },
-});
diff --git a/container/schemas/v2/collection.schema.json b/container/schemas/v2/collection.schema.json
index 5b23227..a7b88cc 100644
--- a/container/schemas/v2/collection.schema.json
+++ b/container/schemas/v2/collection.schema.json
@@ -19,7 +19,6 @@
"additionalProperties": false,
"properties": {
"recipe_id": { "$ref": "common.schema.json#/$defs/id" },
- "recipe_revision": { "$ref": "common.schema.json#/$defs/revision" },
"order": { "type": "integer", "minimum": 1 },
"servings": { "$ref": "common.schema.json#/$defs/positiveDecimal" },
"section": { "type": "string" },
diff --git a/container/schemas/v2/common.schema.json b/container/schemas/v2/common.schema.json
index 768bbeb..abbe8ee 100644
--- a/container/schemas/v2/common.schema.json
+++ b/container/schemas/v2/common.schema.json
@@ -9,7 +9,6 @@
},
"nonEmptyString": { "type": "string", "minLength": 1 },
"schemaVersion": { "const": 2 },
- "revision": { "type": "integer", "minimum": 1 },
"date": { "type": "string", "format": "date" },
"dateTime": { "type": "string", "format": "date-time" },
"decimal": { "type": "number", "minimum": 0 },
diff --git a/container/schemas/v2/derived-recipe.schema.json b/container/schemas/v2/derived-recipe.schema.json
index c061c1c..40936a6 100644
--- a/container/schemas/v2/derived-recipe.schema.json
+++ b/container/schemas/v2/derived-recipe.schema.json
@@ -4,12 +4,11 @@
"title": "Disposable derived recipe values",
"description": "Calculated output. This document is never canonical culinary or purchasing input.",
"type": "object",
- "required": ["schema_version", "recipe_id", "recipe_revision", "calculation_version", "calculated_at", "input_fingerprint"],
+ "required": ["schema_version", "recipe_id", "calculation_version", "calculated_at", "input_fingerprint"],
"additionalProperties": false,
"properties": {
"schema_version": { "$ref": "common.schema.json#/$defs/schemaVersion" },
"recipe_id": { "$ref": "common.schema.json#/$defs/id" },
- "recipe_revision": { "$ref": "common.schema.json#/$defs/revision" },
"calculation_version": { "type": "integer", "minimum": 1 },
"calculated_at": { "$ref": "common.schema.json#/$defs/dateTime" },
"input_fingerprint": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
diff --git a/container/schemas/v2/recipe.schema.json b/container/schemas/v2/recipe.schema.json
index a90a177..1d96ab1 100644
--- a/container/schemas/v2/recipe.schema.json
+++ b/container/schemas/v2/recipe.schema.json
@@ -3,13 +3,11 @@
"$id": "https://recipes.uuard.com/schemas/v2/recipe.schema.json",
"title": "Canonical recipe",
"type": "object",
- "required": ["schema_version", "id", "revision", "status", "title", "yield", "components", "steps", "categories", "tags"],
+ "required": ["schema_version", "id", "title", "yield", "components", "steps", "categories", "tags"],
"additionalProperties": false,
"properties": {
"schema_version": { "$ref": "common.schema.json#/$defs/schemaVersion" },
"id": { "$ref": "common.schema.json#/$defs/id" },
- "revision": { "$ref": "common.schema.json#/$defs/revision" },
- "status": { "type": "string", "enum": ["draft", "testing", "active", "retired", "archived"] },
"title": { "$ref": "common.schema.json#/$defs/nonEmptyString" },
"summary": { "type": "string" },
"categories": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/nonEmptyString" }, "uniqueItems": true },
@@ -113,7 +111,6 @@
"additionalProperties": false,
"properties": {
"recipe_id": { "$ref": "common.schema.json#/$defs/id" },
- "revision": { "$ref": "common.schema.json#/$defs/revision" },
"component_id": { "$ref": "common.schema.json#/$defs/id" }
}
}
diff --git a/culinary/ingredients/beer.yaml b/culinary/ingredients/beer.yaml
index 196c5c3..0fc3e5d 100644
--- a/culinary/ingredients/beer.yaml
+++ b/culinary/ingredients/beer.yaml
@@ -1,30 +1,30 @@
schema_version: 2
-id: beer
-name: Alcoholic beverage, beer, regular, all
-status: active
+id: "beer"
+name: "Alcoholic beverage, beer, regular, all"
+status: "active"
categories:
-- unknown
+ - "beer"
aliases:
-- name: beer
- kind: search
+ - name: "beer"
+ kind: "common"
nutrition_mapping_ids:
-- usda_fdc_beer_168746
+ - "usda_fdc_beer_168746"
allergen_mapping_ids: []
measure_conversions:
-- id: usda_168746_83686
- from:
- quantity: 1.0
- unit_id: fluid_ounce_us
- to:
- quantity: 29.7
- unit_id: gram
- source:
- source_type: usda_fdc
- external_id: '168746'
- url: https://fdc.nal.usda.gov/food-details/168746/measures
- title: Alcoholic beverage, beer, regular, all
- publisher: USDA Agricultural Research Service
- retrieved_at: '2026-08-12'
- reviewed: true
- notes: FoodData Central portion ID 83686.
- reviewed_at: '2026-08-12'
+ - id: "usda_168746_83686"
+ from:
+ quantity: 1
+ unit_id: "fluid_ounce_us"
+ to:
+ quantity: 29.7
+ unit_id: "gram"
+ source:
+ source_type: "usda_fdc"
+ external_id: "168746"
+ url: "https://fdc.nal.usda.gov/food-details/168746/measures"
+ title: "Alcoholic beverage, beer, regular, all"
+ publisher: "USDA Agricultural Research Service"
+ retrieved_at: "2026-08-12"
+ reviewed: true
+ notes: "FoodData Central portion ID 83686."
+ reviewed_at: "2026-08-12"
diff --git a/culinary/recipes/0_recipe_test.yaml b/culinary/recipes/0_recipe_test.yaml
new file mode 100644
index 0000000..a8e6d78
--- /dev/null
+++ b/culinary/recipes/0_recipe_test.yaml
@@ -0,0 +1,33 @@
+schema_version: 2
+id: 0_recipe_test
+title: 0-recipe-test
+categories: []
+tags: []
+yield:
+ amount:
+ quantity: 1000
+ unit_id: gram
+scaling:
+ mode: amount
+components:
+ - id: component_74d895d5
+ name: main
+ items:
+ - id: line_7ea18d07
+ reference:
+ ingredient_id: basil
+ amount:
+ quantity: 300
+ unit_id: gram
+ percentage: 100
+ basis_member: true
+steps:
+ - id: step_1
+ order: 1
+ instruction: place it into the dog shed
+ - id: step_3ef49eca
+ order: 2
+ instruction: assemble the lego set
+ - id: step_4cd4eb90
+ order: 3
+ instruction: become sad
diff --git a/culinary/recipes/alkaline_soy_meat_marinade.yaml b/culinary/recipes/alkaline_soy_meat_marinade.yaml
index d60a280..93d6da6 100644
--- a/culinary/recipes/alkaline_soy_meat_marinade.yaml
+++ b/culinary/recipes/alkaline_soy_meat_marinade.yaml
@@ -1,13 +1,11 @@
schema_version: 2
id: alkaline_soy_meat_marinade
-revision: 1
-status: draft
title: Alkaline Soy Meat Marinade
categories:
-- sauce
+ - sauce
tags:
-- marinade
-- chicken
+ - marinade
+ - chicken
yield:
amount:
quantity: 107.48
@@ -17,44 +15,44 @@ scaling:
mode: hybrid
basis_id: formula_basis
basis_amount:
- quantity: 100.0
+ quantity: 100
unit_id: gram
components:
-- id: main
- name: Main
- items:
- - id: line_01_water
- reference:
- ingredient_id: water
- amount:
- quantity: 100
- unit_id: gram
- percentage: 100
- basis_member: true
- - id: line_02_soy_sauce_light
- reference:
- ingredient_id: soy_sauce_light
- amount:
- quantity: 6.38
- unit_id: gram
- percentage: 6.38
- - id: line_03_baking_soda
- reference:
- ingredient_id: baking_soda
- amount:
- quantity: 1.1
- unit_id: gram
- percentage: 1.1
+ - id: main
+ name: Main
+ items:
+ - id: line_01_water
+ reference:
+ ingredient_id: water
+ amount:
+ quantity: 100
+ unit_id: gram
+ percentage: 100
+ basis_member: true
+ - id: line_02_soy_sauce_light
+ reference:
+ ingredient_id: soy_sauce_light
+ amount:
+ quantity: 6.38
+ unit_id: gram
+ percentage: 6.38
+ - id: line_03_baking_soda
+ reference:
+ ingredient_id: baking_soda
+ amount:
+ quantity: 1.1
+ unit_id: gram
+ percentage: 1.1
steps:
-- id: step_01
- order: 1
- instruction: Combine.
- component_ids:
- - main
-- id: step_02
- order: 2
- instruction: Mix until dissolved.
- component_ids:
- - main
+ - id: step_01
+ order: 1
+ instruction: Combine.
+ component_ids:
+ - main
+ - id: step_02
+ order: 2
+ instruction: Mix until dissolved.
+ component_ids:
+ - main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+ - Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/amorosos_roll.yaml b/culinary/recipes/amorosos_roll.yaml
index be5f806..10695ef 100644
--- a/culinary/recipes/amorosos_roll.yaml
+++ b/culinary/recipes/amorosos_roll.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: amorosos_roll
-revision: 1
-status: draft
title: Amoroso's Roll
categories:
- bread
@@ -81,4 +79,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/apricot_glaze.yaml b/culinary/recipes/apricot_glaze.yaml
index ee40904..e63f2ee 100644
--- a/culinary/recipes/apricot_glaze.yaml
+++ b/culinary/recipes/apricot_glaze.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: apricot_glaze
-revision: 1
-status: draft
title: Apricot Glaze
categories:
- sauce
@@ -82,4 +80,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/auntie_annes_pretzels.yaml b/culinary/recipes/auntie_annes_pretzels.yaml
index e83b96d..6256a57 100644
--- a/culinary/recipes/auntie_annes_pretzels.yaml
+++ b/culinary/recipes/auntie_annes_pretzels.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: auntie_annes_pretzels
-revision: 1
-status: draft
title: Auntie Anne's Pretzels
categories:
- bread
@@ -131,4 +129,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/bagel.yaml b/culinary/recipes/bagel.yaml
index f6bd819..a08cd1f 100644
--- a/culinary/recipes/bagel.yaml
+++ b/culinary/recipes/bagel.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: bagel
-revision: 1
-status: draft
title: Bagel
categories:
- bread
@@ -65,4 +63,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/baileys_sourdough.yaml b/culinary/recipes/baileys_sourdough.yaml
index c5f0381..7ce205f 100644
--- a/culinary/recipes/baileys_sourdough.yaml
+++ b/culinary/recipes/baileys_sourdough.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: baileys_sourdough
-revision: 1
-status: draft
title: Bailey's Sourdough
categories:
- bread
@@ -170,4 +168,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/banana_bread.yaml b/culinary/recipes/banana_bread.yaml
index 4ae85c6..39ead7d 100644
--- a/culinary/recipes/banana_bread.yaml
+++ b/culinary/recipes/banana_bread.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: banana_bread
-revision: 1
-status: draft
title: Banana Bread
categories:
- dessert
@@ -114,4 +112,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/beer_cheese.yaml b/culinary/recipes/beer_cheese.yaml
index 15acd82..ca33458 100644
--- a/culinary/recipes/beer_cheese.yaml
+++ b/culinary/recipes/beer_cheese.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: beer_cheese
-revision: 1
-status: draft
title: Beer Cheese
categories:
- sauce
@@ -130,4 +128,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/benihana_yum_yum_sauce.yaml b/culinary/recipes/benihana_yum_yum_sauce.yaml
index f58937e..83c9a51 100644
--- a/culinary/recipes/benihana_yum_yum_sauce.yaml
+++ b/culinary/recipes/benihana_yum_yum_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: benihana_yum_yum_sauce
-revision: 1
-status: draft
title: Benihana Yum Yum Sauce
categories:
- sauce
@@ -122,4 +120,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/berry_bagel.yaml b/culinary/recipes/berry_bagel.yaml
index 07a1402..10fc0f3 100644
--- a/culinary/recipes/berry_bagel.yaml
+++ b/culinary/recipes/berry_bagel.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: berry_bagel
-revision: 1
-status: draft
title: Berry Bagel
categories:
- bread
@@ -148,4 +146,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/berry_muffin.yaml b/culinary/recipes/berry_muffin.yaml
index b894358..bdedf36 100644
--- a/culinary/recipes/berry_muffin.yaml
+++ b/culinary/recipes/berry_muffin.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: berry_muffin
-revision: 1
-status: draft
title: Berry Muffin
categories:
- dessert
@@ -120,4 +118,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/blueberry_raspberry_blend.yaml b/culinary/recipes/blueberry_raspberry_blend.yaml
index 83bee40..a989dc8 100644
--- a/culinary/recipes/blueberry_raspberry_blend.yaml
+++ b/culinary/recipes/blueberry_raspberry_blend.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: blueberry_raspberry_blend
-revision: 1
-status: active
title: Blueberry–Raspberry Blend
categories:
- component
diff --git a/culinary/recipes/broccoli_cheddar_soup.yaml b/culinary/recipes/broccoli_cheddar_soup.yaml
index bfc07a2..6ae364e 100644
--- a/culinary/recipes/broccoli_cheddar_soup.yaml
+++ b/culinary/recipes/broccoli_cheddar_soup.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: broccoli_cheddar_soup
-revision: 1
-status: draft
title: Broccoli Cheddar Soup
categories:
- soup
@@ -219,4 +217,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/buttercream.yaml b/culinary/recipes/buttercream.yaml
index b284e22..ea00b12 100644
--- a/culinary/recipes/buttercream.yaml
+++ b/culinary/recipes/buttercream.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: buttercream
-revision: 1
-status: draft
title: Buttercream
categories:
- sauce
@@ -82,4 +80,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/buttermilk_biscuits.yaml b/culinary/recipes/buttermilk_biscuits.yaml
index a8c1696..100fd0a 100644
--- a/culinary/recipes/buttermilk_biscuits.yaml
+++ b/culinary/recipes/buttermilk_biscuits.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: buttermilk_biscuits
-revision: 1
-status: draft
title: Buttermilk Biscuits
categories:
- bread
@@ -134,4 +132,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/caramel_sauce.yaml b/culinary/recipes/caramel_sauce.yaml
index d741161..f20162f 100644
--- a/culinary/recipes/caramel_sauce.yaml
+++ b/culinary/recipes/caramel_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: caramel_sauce
-revision: 1
-status: draft
title: Caramel Sauce
categories:
- sauce
@@ -117,4 +115,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/caramelized_onion.yaml b/culinary/recipes/caramelized_onion.yaml
index a044db9..f342ffe 100644
--- a/culinary/recipes/caramelized_onion.yaml
+++ b/culinary/recipes/caramelized_onion.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: caramelized_onion
-revision: 1
-status: draft
title: Caramelized Onion
categories:
- side
@@ -99,4 +97,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/carrot_soup.yaml b/culinary/recipes/carrot_soup.yaml
index 74a4b6e..e2de7dd 100644
--- a/culinary/recipes/carrot_soup.yaml
+++ b/culinary/recipes/carrot_soup.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: carrot_soup
-revision: 1
-status: draft
title: Carrot Soup
categories:
- soup
@@ -69,4 +67,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/cheese_danish_filling.yaml b/culinary/recipes/cheese_danish_filling.yaml
index a907e6b..9e0c255 100644
--- a/culinary/recipes/cheese_danish_filling.yaml
+++ b/culinary/recipes/cheese_danish_filling.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: cheese_danish_filling
-revision: 1
-status: draft
title: Cheese Danish Filling
categories:
- pastry
@@ -84,4 +82,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/cheesecake.yaml b/culinary/recipes/cheesecake.yaml
index ef1f175..c1454f6 100644
--- a/culinary/recipes/cheesecake.yaml
+++ b/culinary/recipes/cheesecake.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: cheesecake
-revision: 1
-status: draft
title: Cheesecake
categories:
- dessert
@@ -154,4 +152,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/chick_fil_a_sauce.yaml b/culinary/recipes/chick_fil_a_sauce.yaml
index f7d47c9..3899b82 100644
--- a/culinary/recipes/chick_fil_a_sauce.yaml
+++ b/culinary/recipes/chick_fil_a_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: chick_fil_a_sauce
-revision: 1
-status: draft
title: Chick-fil-A Sauce
categories:
- sauce
@@ -61,4 +59,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/chicken_sausage.yaml b/culinary/recipes/chicken_sausage.yaml
index 67152f8..7cc43b8 100644
--- a/culinary/recipes/chicken_sausage.yaml
+++ b/culinary/recipes/chicken_sausage.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: chicken_sausage
-revision: 1
-status: draft
title: Chicken Sausage
categories:
- meat
@@ -152,4 +150,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/chicken_velvet.yaml b/culinary/recipes/chicken_velvet.yaml
index 60e74b4..5e2e5b5 100644
--- a/culinary/recipes/chicken_velvet.yaml
+++ b/culinary/recipes/chicken_velvet.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: chicken_velvet
-revision: 1
-status: draft
title: Chicken Velvet
categories:
- meat
@@ -102,4 +100,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/chilis_avocado_ranch.yaml b/culinary/recipes/chilis_avocado_ranch.yaml
index d8f9bf5..74b557c 100644
--- a/culinary/recipes/chilis_avocado_ranch.yaml
+++ b/culinary/recipes/chilis_avocado_ranch.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: chilis_avocado_ranch
-revision: 1
-status: draft
title: Chili's Avocado Ranch
categories:
- sauce
@@ -54,4 +52,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/chipotle_pinto_beans.yaml b/culinary/recipes/chipotle_pinto_beans.yaml
index edc2ae0..1d13dbf 100644
--- a/culinary/recipes/chipotle_pinto_beans.yaml
+++ b/culinary/recipes/chipotle_pinto_beans.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: chipotle_pinto_beans
-revision: 1
-status: draft
title: Chipotle Pinto Beans
categories:
- side
@@ -131,4 +129,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/chocolate_biscotti.yaml b/culinary/recipes/chocolate_biscotti.yaml
index bbf0b44..ac64975 100644
--- a/culinary/recipes/chocolate_biscotti.yaml
+++ b/culinary/recipes/chocolate_biscotti.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: chocolate_biscotti
-revision: 1
-status: draft
title: Chocolate Biscotti
categories:
- dessert
@@ -164,4 +162,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/chocolate_chip_cookie.yaml b/culinary/recipes/chocolate_chip_cookie.yaml
index 93e4da9..f1c012d 100644
--- a/culinary/recipes/chocolate_chip_cookie.yaml
+++ b/culinary/recipes/chocolate_chip_cookie.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: chocolate_chip_cookie
-revision: 1
-status: draft
title: Chocolate Chip Cookie
categories:
- dessert
@@ -150,4 +148,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/chocolate_ganache.yaml b/culinary/recipes/chocolate_ganache.yaml
index f3f6d5b..6868fbb 100644
--- a/culinary/recipes/chocolate_ganache.yaml
+++ b/culinary/recipes/chocolate_ganache.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: chocolate_ganache
-revision: 1
-status: draft
title: Chocolate Ganache
categories:
- sauce
@@ -50,4 +48,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/chow_mein_sauce.yaml b/culinary/recipes/chow_mein_sauce.yaml
index 0e817b9..8bdeaa2 100644
--- a/culinary/recipes/chow_mein_sauce.yaml
+++ b/culinary/recipes/chow_mein_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: chow_mein_sauce
-revision: 1
-status: draft
title: Chow Mein Sauce
categories:
- sauce
@@ -100,4 +98,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/cilantro_lime_rice.yaml b/culinary/recipes/cilantro_lime_rice.yaml
index 418f4e9..a639484 100644
--- a/culinary/recipes/cilantro_lime_rice.yaml
+++ b/culinary/recipes/cilantro_lime_rice.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: cilantro_lime_rice
-revision: 1
-status: draft
title: Cilantro Lime Rice
categories:
- side
@@ -101,4 +99,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/cinnamon_crunch_bagel.yaml b/culinary/recipes/cinnamon_crunch_bagel.yaml
index a20cf2f..1f6ba9e 100644
--- a/culinary/recipes/cinnamon_crunch_bagel.yaml
+++ b/culinary/recipes/cinnamon_crunch_bagel.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: cinnamon_crunch_bagel
-revision: 1
-status: draft
title: Cinnamon Crunch Bagel
categories:
- bread
@@ -79,4 +77,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/cinnamon_filling.yaml b/culinary/recipes/cinnamon_filling.yaml
index 4fc25ab..0566c35 100644
--- a/culinary/recipes/cinnamon_filling.yaml
+++ b/culinary/recipes/cinnamon_filling.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: cinnamon_filling
-revision: 1
-status: draft
title: Cinnamon Filling
categories:
- component
@@ -79,4 +77,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/cinnamon_roll.yaml b/culinary/recipes/cinnamon_roll.yaml
index 0eb4337..d5994f7 100644
--- a/culinary/recipes/cinnamon_roll.yaml
+++ b/culinary/recipes/cinnamon_roll.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: cinnamon_roll
-revision: 1
-status: draft
title: Cinnamon Roll
categories:
- bread
@@ -196,4 +194,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/cinnamon_sugar.yaml b/culinary/recipes/cinnamon_sugar.yaml
index a61dca3..6862952 100644
--- a/culinary/recipes/cinnamon_sugar.yaml
+++ b/culinary/recipes/cinnamon_sugar.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: cinnamon_sugar
-revision: 1
-status: draft
title: Cinnamon Sugar
categories:
- component
@@ -51,4 +49,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/crab_rangoon.yaml b/culinary/recipes/crab_rangoon.yaml
index a134a50..63a69ef 100644
--- a/culinary/recipes/crab_rangoon.yaml
+++ b/culinary/recipes/crab_rangoon.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: crab_rangoon
-revision: 1
-status: draft
title: Crab Rangoon
categories:
- side
@@ -120,4 +118,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/cream_cheese_icing.yaml b/culinary/recipes/cream_cheese_icing.yaml
index d14b9aa..1c0511d 100644
--- a/culinary/recipes/cream_cheese_icing.yaml
+++ b/culinary/recipes/cream_cheese_icing.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: cream_cheese_icing
-revision: 1
-status: draft
title: Cream Cheese Icing
categories:
- sauce
@@ -68,4 +66,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/cream_cheese_icing_2.yaml b/culinary/recipes/cream_cheese_icing_2.yaml
index 9a0d2bf..dd4332a 100644
--- a/culinary/recipes/cream_cheese_icing_2.yaml
+++ b/culinary/recipes/cream_cheese_icing_2.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: cream_cheese_icing_2
-revision: 1
-status: draft
title: Cream Cheese Icing 2
categories:
- sauce
@@ -125,4 +123,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/creamed_berry_muffin.yaml b/culinary/recipes/creamed_berry_muffin.yaml
index b508c04..97463bf 100644
--- a/culinary/recipes/creamed_berry_muffin.yaml
+++ b/culinary/recipes/creamed_berry_muffin.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: creamed_berry_muffin
-revision: 1
-status: draft
title: Creamed Berry Muffin
categories:
- dessert
@@ -140,4 +138,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/creamed_chocolate_chip_muffin.yaml b/culinary/recipes/creamed_chocolate_chip_muffin.yaml
index f8353c6..bd0cae3 100644
--- a/culinary/recipes/creamed_chocolate_chip_muffin.yaml
+++ b/culinary/recipes/creamed_chocolate_chip_muffin.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: creamed_chocolate_chip_muffin
-revision: 1
-status: draft
title: Creamed Chocolate Chip Muffin
categories:
- dessert
@@ -142,4 +140,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/cuban_mustard_mayo.yaml b/culinary/recipes/cuban_mustard_mayo.yaml
index 2b06116..d63dd4d 100644
--- a/culinary/recipes/cuban_mustard_mayo.yaml
+++ b/culinary/recipes/cuban_mustard_mayo.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: cuban_mustard_mayo
-revision: 1
-status: draft
title: Cuban Mustard Mayo
categories:
- sauce
@@ -44,4 +42,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/dark_espresso_brownie.yaml b/culinary/recipes/dark_espresso_brownie.yaml
index 6bba9aa..8919791 100644
--- a/culinary/recipes/dark_espresso_brownie.yaml
+++ b/culinary/recipes/dark_espresso_brownie.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: dark_espresso_brownie
-revision: 1
-status: draft
title: Dark Espresso Brownie
categories:
- dessert
@@ -153,4 +151,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/dinner_rolls.yaml b/culinary/recipes/dinner_rolls.yaml
index 8cacb3b..d1e1e76 100644
--- a/culinary/recipes/dinner_rolls.yaml
+++ b/culinary/recipes/dinner_rolls.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: dinner_rolls
-revision: 1
-status: draft
title: Dinner Rolls
categories:
- bread
@@ -133,4 +131,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/dominos_cheddar_cheese_blend.yaml b/culinary/recipes/dominos_cheddar_cheese_blend.yaml
index 931ef10..bf798f6 100644
--- a/culinary/recipes/dominos_cheddar_cheese_blend.yaml
+++ b/culinary/recipes/dominos_cheddar_cheese_blend.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: dominos_cheddar_cheese_blend
-revision: 1
-status: testing
title: Domino's-Style Cheddar Cheese Blend
summary: A home-scale approximation of Domino's proprietary cheddar and pizza-cheese blend.
categories: [component]
diff --git a/culinary/recipes/dominos_garlic_oil_blend.yaml b/culinary/recipes/dominos_garlic_oil_blend.yaml
index b44616d..ec24cd5 100644
--- a/culinary/recipes/dominos_garlic_oil_blend.yaml
+++ b/culinary/recipes/dominos_garlic_oil_blend.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: dominos_garlic_oil_blend
-revision: 1
-status: draft
title: Domino's Garlic Oil Blend
categories:
- sauce
@@ -110,4 +108,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/dominos_oregano_marjoram_blend.yaml b/culinary/recipes/dominos_oregano_marjoram_blend.yaml
index 33c66d7..48003e4 100644
--- a/culinary/recipes/dominos_oregano_marjoram_blend.yaml
+++ b/culinary/recipes/dominos_oregano_marjoram_blend.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: dominos_oregano_marjoram_blend
-revision: 1
-status: draft
title: Domino's-Style Oregano–Marjoram Blend
categories:
- component
diff --git a/culinary/recipes/dominos_pizza.yaml b/culinary/recipes/dominos_pizza.yaml
index 7b4c209..2171373 100644
--- a/culinary/recipes/dominos_pizza.yaml
+++ b/culinary/recipes/dominos_pizza.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: dominos_pizza
-revision: 1
-status: draft
title: Domino's Pizza Dough
categories:
- bread
@@ -111,4 +109,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/dominos_pizza_sauce.yaml b/culinary/recipes/dominos_pizza_sauce.yaml
index 7c58713..869d8d1 100644
--- a/culinary/recipes/dominos_pizza_sauce.yaml
+++ b/culinary/recipes/dominos_pizza_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: dominos_pizza_sauce
-revision: 1
-status: draft
title: Domino's Pizza Sauce
categories:
- sauce
@@ -69,4 +67,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/dominos_pizza_sauce_v2.yaml b/culinary/recipes/dominos_pizza_sauce_v2.yaml
index 199c319..c9d418d 100644
--- a/culinary/recipes/dominos_pizza_sauce_v2.yaml
+++ b/culinary/recipes/dominos_pizza_sauce_v2.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: dominos_pizza_sauce_v2
-revision: 1
-status: draft
title: Domino's Pizza Sauce V2
categories:
- sauce
@@ -146,4 +144,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/dominos_pizza_sauce_v3.yaml b/culinary/recipes/dominos_pizza_sauce_v3.yaml
index 8b121dd..1c952c7 100644
--- a/culinary/recipes/dominos_pizza_sauce_v3.yaml
+++ b/culinary/recipes/dominos_pizza_sauce_v3.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: dominos_pizza_sauce_v3
-revision: 1
-status: draft
title: Domino's Pizza Sauce V3
categories:
- sauce
@@ -153,4 +151,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/dominos_stuffed_cheesy_bread.yaml b/culinary/recipes/dominos_stuffed_cheesy_bread.yaml
index 34fee95..700b5ed 100644
--- a/culinary/recipes/dominos_stuffed_cheesy_bread.yaml
+++ b/culinary/recipes/dominos_stuffed_cheesy_bread.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: dominos_stuffed_cheesy_bread
-revision: 1
-status: draft
title: Domino's Stuffed Cheesy Bread
categories:
- bread
@@ -112,4 +110,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/donuts.yaml b/culinary/recipes/donuts.yaml
index dc958cb..30e7720 100644
--- a/culinary/recipes/donuts.yaml
+++ b/culinary/recipes/donuts.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: donuts
-revision: 1
-status: draft
title: Donuts
categories:
- dessert
@@ -147,4 +145,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/egg_noodle.yaml b/culinary/recipes/egg_noodle.yaml
index d4dda71..7fb1121 100644
--- a/culinary/recipes/egg_noodle.yaml
+++ b/culinary/recipes/egg_noodle.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: egg_noodle
-revision: 1
-status: draft
title: Egg Noodle
categories:
- side
@@ -58,4 +56,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/egg_replacer.yaml b/culinary/recipes/egg_replacer.yaml
index 797241f..06d815a 100644
--- a/culinary/recipes/egg_replacer.yaml
+++ b/culinary/recipes/egg_replacer.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: egg_replacer
-revision: 1
-status: draft
title: Egg Replacer
categories:
- component
@@ -65,4 +63,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/english_muffin.yaml b/culinary/recipes/english_muffin.yaml
index f69d077..6f28c57 100644
--- a/culinary/recipes/english_muffin.yaml
+++ b/culinary/recipes/english_muffin.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: english_muffin
-revision: 1
-status: draft
title: English Muffin
categories:
- bread
@@ -121,4 +119,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/focaccia.yaml b/culinary/recipes/focaccia.yaml
index a245664..cc2d375 100644
--- a/culinary/recipes/focaccia.yaml
+++ b/culinary/recipes/focaccia.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: focaccia
-revision: 1
-status: draft
title: Focaccia
categories:
- bread
@@ -124,4 +122,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/fried_rice.yaml b/culinary/recipes/fried_rice.yaml
index 74f476c..00f5a99 100644
--- a/culinary/recipes/fried_rice.yaml
+++ b/culinary/recipes/fried_rice.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: fried_rice
-revision: 1
-status: draft
title: Fried Rice
categories:
- side
@@ -149,4 +147,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/general_tso_sauce.yaml b/culinary/recipes/general_tso_sauce.yaml
index 7a5eba0..9500da1 100644
--- a/culinary/recipes/general_tso_sauce.yaml
+++ b/culinary/recipes/general_tso_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: general_tso_sauce
-revision: 1
-status: draft
title: General Tso's Sauce
categories:
- sauce
@@ -135,4 +133,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/ginger_molasses_cookie.yaml b/culinary/recipes/ginger_molasses_cookie.yaml
index 6476216..4ec2935 100644
--- a/culinary/recipes/ginger_molasses_cookie.yaml
+++ b/culinary/recipes/ginger_molasses_cookie.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: ginger_molasses_cookie
-revision: 1
-status: draft
title: Ginger Molasses Cookie
categories:
- dessert
@@ -143,4 +141,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/graham_cracker_crust.yaml b/culinary/recipes/graham_cracker_crust.yaml
index ace78f1..ed7c4f7 100644
--- a/culinary/recipes/graham_cracker_crust.yaml
+++ b/culinary/recipes/graham_cracker_crust.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: graham_cracker_crust
-revision: 1
-status: draft
title: Graham Cracker Crust
categories:
- pastry
@@ -70,4 +68,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/gravy.yaml b/culinary/recipes/gravy.yaml
index a4164e5..dcd9b24 100644
--- a/culinary/recipes/gravy.yaml
+++ b/culinary/recipes/gravy.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: gravy
-revision: 1
-status: draft
title: Gravy
categories:
- sauce
@@ -89,4 +87,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/guacamole.yaml b/culinary/recipes/guacamole.yaml
index 057421f..b6c59e3 100644
--- a/culinary/recipes/guacamole.yaml
+++ b/culinary/recipes/guacamole.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: guacamole
-revision: 1
-status: draft
title: Guacamole
categories:
- side
@@ -91,4 +89,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/gyro_meat.yaml b/culinary/recipes/gyro_meat.yaml
index 19d3071..82bba2f 100644
--- a/culinary/recipes/gyro_meat.yaml
+++ b/culinary/recipes/gyro_meat.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: gyro_meat
-revision: 1
-status: draft
title: Gyro Meat
categories:
- meat
@@ -181,4 +179,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/halal_guys_white_sauce_v1.yaml b/culinary/recipes/halal_guys_white_sauce_v1.yaml
index b4556ee..f763e59 100644
--- a/culinary/recipes/halal_guys_white_sauce_v1.yaml
+++ b/culinary/recipes/halal_guys_white_sauce_v1.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: halal_guys_white_sauce_v1
-revision: 1
-status: draft
title: Halal Guys White Sauce V1
categories:
- sauce
@@ -66,4 +64,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/halal_guys_white_sauce_v2.yaml b/culinary/recipes/halal_guys_white_sauce_v2.yaml
index 261dc68..140ae2f 100644
--- a/culinary/recipes/halal_guys_white_sauce_v2.yaml
+++ b/culinary/recipes/halal_guys_white_sauce_v2.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: halal_guys_white_sauce_v2
-revision: 1
-status: draft
title: Halal Guys White Sauce V2
categories:
- sauce
@@ -73,4 +71,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/hamburger_bun.yaml b/culinary/recipes/hamburger_bun.yaml
index a9b3185..e89d8f4 100644
--- a/culinary/recipes/hamburger_bun.yaml
+++ b/culinary/recipes/hamburger_bun.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: hamburger_bun
-revision: 1
-status: draft
title: Hamburger Bun
categories:
- bread
@@ -115,4 +113,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/hoagie.yaml b/culinary/recipes/hoagie.yaml
index 946b300..de6baa1 100644
--- a/culinary/recipes/hoagie.yaml
+++ b/culinary/recipes/hoagie.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: hoagie
-revision: 1
-status: draft
title: Hoagie
categories:
- bread
@@ -72,4 +70,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/hot_fudge_v1.yaml b/culinary/recipes/hot_fudge_v1.yaml
index 74ccced..a4b3bc4 100644
--- a/culinary/recipes/hot_fudge_v1.yaml
+++ b/culinary/recipes/hot_fudge_v1.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: hot_fudge_v1
-revision: 1
-status: draft
title: Hot Fudge V1
categories:
- sauce
@@ -88,4 +86,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/hot_fudge_v2.yaml b/culinary/recipes/hot_fudge_v2.yaml
index 0668d09..ab05c5b 100644
--- a/culinary/recipes/hot_fudge_v2.yaml
+++ b/culinary/recipes/hot_fudge_v2.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: hot_fudge_v2
-revision: 1
-status: draft
title: Hot Fudge V2
categories:
- sauce
@@ -117,4 +115,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/imos_pizza_dough.yaml b/culinary/recipes/imos_pizza_dough.yaml
index 80c3ad1..8609e47 100644
--- a/culinary/recipes/imos_pizza_dough.yaml
+++ b/culinary/recipes/imos_pizza_dough.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: imos_pizza_dough
-revision: 1
-status: draft
title: Imo's Pizza Dough
categories:
- bread
@@ -105,4 +103,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/jimmy_johns_kickin_ranch_sauce.yaml b/culinary/recipes/jimmy_johns_kickin_ranch_sauce.yaml
index bb5c666..272fb34 100644
--- a/culinary/recipes/jimmy_johns_kickin_ranch_sauce.yaml
+++ b/culinary/recipes/jimmy_johns_kickin_ranch_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: jimmy_johns_kickin_ranch_sauce
-revision: 1
-status: draft
title: Jimmy John's Kickin' Ranch Sauce
categories:
- sauce
@@ -94,4 +92,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/korean_coater_mix.yaml b/culinary/recipes/korean_coater_mix.yaml
index b9dc94a..3977dd8 100644
--- a/culinary/recipes/korean_coater_mix.yaml
+++ b/culinary/recipes/korean_coater_mix.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: korean_coater_mix
-revision: 1
-status: draft
title: Korean Coater Mix
categories:
- component
@@ -70,4 +68,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/korean_fry_batter.yaml b/culinary/recipes/korean_fry_batter.yaml
index 85f93a6..0a33d18 100644
--- a/culinary/recipes/korean_fry_batter.yaml
+++ b/culinary/recipes/korean_fry_batter.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: korean_fry_batter
-revision: 1
-status: draft
title: Korean Fry Batter
categories:
- component
@@ -86,4 +84,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/lemon_curd.yaml b/culinary/recipes/lemon_curd.yaml
index 985a510..557dc2e 100644
--- a/culinary/recipes/lemon_curd.yaml
+++ b/culinary/recipes/lemon_curd.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: lemon_curd
-revision: 1
-status: draft
title: Lemon Curd
categories:
- sauce
@@ -90,4 +88,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/lo_mein_sauce.yaml b/culinary/recipes/lo_mein_sauce.yaml
index 5afbb55..b2b51dd 100644
--- a/culinary/recipes/lo_mein_sauce.yaml
+++ b/culinary/recipes/lo_mein_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: lo_mein_sauce
-revision: 1
-status: draft
title: Lo Mein Sauce
categories:
- sauce
@@ -98,4 +96,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/mac_cheese_sauce.yaml b/culinary/recipes/mac_cheese_sauce.yaml
index 1d8ca10..25ef4aa 100644
--- a/culinary/recipes/mac_cheese_sauce.yaml
+++ b/culinary/recipes/mac_cheese_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: mac_cheese_sauce
-revision: 1
-status: draft
title: Mac & Cheese Sauce
categories:
- sauce
@@ -63,4 +61,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/mashed_potato.yaml b/culinary/recipes/mashed_potato.yaml
index 3e58b6b..a92501e 100644
--- a/culinary/recipes/mashed_potato.yaml
+++ b/culinary/recipes/mashed_potato.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: mashed_potato
-revision: 1
-status: draft
title: Mashed Potato
categories:
- side
@@ -78,4 +76,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/meatball.yaml b/culinary/recipes/meatball.yaml
index c1c16e8..4ee1f76 100644
--- a/culinary/recipes/meatball.yaml
+++ b/culinary/recipes/meatball.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: meatball
-revision: 1
-status: draft
title: Meatball
categories:
- meat
@@ -153,4 +151,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/mexicali_dip.yaml b/culinary/recipes/mexicali_dip.yaml
index bb64aac..63283db 100644
--- a/culinary/recipes/mexicali_dip.yaml
+++ b/culinary/recipes/mexicali_dip.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: mexicali_dip
-revision: 1
-status: draft
title: Mexicali Dip
categories:
- sauce
@@ -94,4 +92,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/mexican_rice.yaml b/culinary/recipes/mexican_rice.yaml
index a434ddb..2669492 100644
--- a/culinary/recipes/mexican_rice.yaml
+++ b/culinary/recipes/mexican_rice.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: mexican_rice
-revision: 1
-status: draft
title: Mexican Rice
categories:
- side
@@ -92,4 +90,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/mexican_white_sauce.yaml b/culinary/recipes/mexican_white_sauce.yaml
index 1f62aca..6d1ebbc 100644
--- a/culinary/recipes/mexican_white_sauce.yaml
+++ b/culinary/recipes/mexican_white_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: mexican_white_sauce
-revision: 1
-status: draft
title: Mexican White Sauce
categories:
- sauce
@@ -135,4 +133,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/milk.yaml b/culinary/recipes/milk.yaml
index 70f056e..230ee27 100644
--- a/culinary/recipes/milk.yaml
+++ b/culinary/recipes/milk.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: milk
-revision: 1
-status: draft
title: Milk
categories:
- component
@@ -44,4 +42,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/mod_pizza_dough.yaml b/culinary/recipes/mod_pizza_dough.yaml
index 815b0c5..1485ac0 100644
--- a/culinary/recipes/mod_pizza_dough.yaml
+++ b/culinary/recipes/mod_pizza_dough.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: mod_pizza_dough
-revision: 1
-status: draft
title: MOD Pizza Dough
categories:
- bread
@@ -95,4 +93,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/mozzarella_cheese_melt_stuffed.yaml b/culinary/recipes/mozzarella_cheese_melt_stuffed.yaml
index 4bd558d..377eca0 100644
--- a/culinary/recipes/mozzarella_cheese_melt_stuffed.yaml
+++ b/culinary/recipes/mozzarella_cheese_melt_stuffed.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: mozzarella_cheese_melt_stuffed
-revision: 1
-status: draft
title: Mozzarella Cheese Melt Stuffed
categories:
- component
@@ -70,4 +68,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/oat_chocolate_cookie.yaml b/culinary/recipes/oat_chocolate_cookie.yaml
index e9ec911..e8679a8 100644
--- a/culinary/recipes/oat_chocolate_cookie.yaml
+++ b/culinary/recipes/oat_chocolate_cookie.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: oat_chocolate_cookie
-revision: 1
-status: draft
title: Oat Chocolate Cookie
categories:
- dessert
@@ -134,4 +132,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/oatmeal_raisin_cookie.yaml b/culinary/recipes/oatmeal_raisin_cookie.yaml
index 379d7e9..7173deb 100644
--- a/culinary/recipes/oatmeal_raisin_cookie.yaml
+++ b/culinary/recipes/oatmeal_raisin_cookie.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: oatmeal_raisin_cookie
-revision: 1
-status: draft
title: Oatmeal Raisin Cookie
categories:
- dessert
@@ -100,4 +98,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/orange_chicken_sauce.yaml b/culinary/recipes/orange_chicken_sauce.yaml
index 2362146..64786fe 100644
--- a/culinary/recipes/orange_chicken_sauce.yaml
+++ b/culinary/recipes/orange_chicken_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: orange_chicken_sauce
-revision: 1
-status: draft
title: Orange Chicken Sauce
categories:
- sauce
@@ -183,4 +181,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/orange_juice.yaml b/culinary/recipes/orange_juice.yaml
index 5c348d1..8e6a3da 100644
--- a/culinary/recipes/orange_juice.yaml
+++ b/culinary/recipes/orange_juice.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: orange_juice
-revision: 1
-status: draft
title: Orange Juice
categories:
- beverage
@@ -43,4 +41,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/p_f_changs_dark_sauce.yaml b/culinary/recipes/p_f_changs_dark_sauce.yaml
index ddec076..1297ff8 100644
--- a/culinary/recipes/p_f_changs_dark_sauce.yaml
+++ b/culinary/recipes/p_f_changs_dark_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: p_f_changs_dark_sauce
-revision: 1
-status: draft
title: P. F. Chang's Dark Sauce
categories:
- sauce
@@ -93,4 +91,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/p_f_changs_honey_sauce.yaml b/culinary/recipes/p_f_changs_honey_sauce.yaml
index ce370b0..a0e61cb 100644
--- a/culinary/recipes/p_f_changs_honey_sauce.yaml
+++ b/culinary/recipes/p_f_changs_honey_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: p_f_changs_honey_sauce
-revision: 1
-status: draft
title: P. F. Chang's Honey Sauce
categories:
- sauce
@@ -134,4 +132,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/p_f_changs_kung_pao_sauce.yaml b/culinary/recipes/p_f_changs_kung_pao_sauce.yaml
index c4ac6ba..76790a0 100644
--- a/culinary/recipes/p_f_changs_kung_pao_sauce.yaml
+++ b/culinary/recipes/p_f_changs_kung_pao_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: p_f_changs_kung_pao_sauce
-revision: 1
-status: draft
title: P. F. Chang's Kung Pao Sauce
categories:
- sauce
@@ -88,4 +86,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/p_f_changs_mongolian_beef_sauce.yaml b/culinary/recipes/p_f_changs_mongolian_beef_sauce.yaml
index 017823b..9d43c0f 100644
--- a/culinary/recipes/p_f_changs_mongolian_beef_sauce.yaml
+++ b/culinary/recipes/p_f_changs_mongolian_beef_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: p_f_changs_mongolian_beef_sauce
-revision: 1
-status: draft
title: P. F. Chang's Mongolian Beef Sauce
categories:
- sauce
@@ -99,4 +97,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/p_f_changs_spicy_chicken_sauce.yaml b/culinary/recipes/p_f_changs_spicy_chicken_sauce.yaml
index df4d9e5..37aa0b6 100644
--- a/culinary/recipes/p_f_changs_spicy_chicken_sauce.yaml
+++ b/culinary/recipes/p_f_changs_spicy_chicken_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: p_f_changs_spicy_chicken_sauce
-revision: 1
-status: draft
title: P. F. Chang's Spicy Chicken Sauce
categories:
- sauce
@@ -101,4 +99,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/p_f_changs_umami_sauce.yaml b/culinary/recipes/p_f_changs_umami_sauce.yaml
index 761d882..656aa30 100644
--- a/culinary/recipes/p_f_changs_umami_sauce.yaml
+++ b/culinary/recipes/p_f_changs_umami_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: p_f_changs_umami_sauce
-revision: 1
-status: draft
title: P. F. Chang's Umami Sauce
categories:
- sauce
@@ -75,4 +73,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/pancakes.yaml b/culinary/recipes/pancakes.yaml
index d07a377..b9f9b38 100644
--- a/culinary/recipes/pancakes.yaml
+++ b/culinary/recipes/pancakes.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: pancakes
-revision: 1
-status: draft
title: Pancakes
categories:
- breakfast
@@ -108,4 +106,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/papa_johns_garlic_dipping_sauce.yaml b/culinary/recipes/papa_johns_garlic_dipping_sauce.yaml
index 00c517f..32b74cc 100644
--- a/culinary/recipes/papa_johns_garlic_dipping_sauce.yaml
+++ b/culinary/recipes/papa_johns_garlic_dipping_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: papa_johns_garlic_dipping_sauce
-revision: 1
-status: draft
title: Papa Johns Garlic Dipping Sauce
categories:
- sauce
@@ -89,4 +87,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/papa_johns_pizza.yaml b/culinary/recipes/papa_johns_pizza.yaml
index c9ffe56..f03bb57 100644
--- a/culinary/recipes/papa_johns_pizza.yaml
+++ b/culinary/recipes/papa_johns_pizza.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: papa_johns_pizza
-revision: 1
-status: draft
title: Papa Johns Pizza
categories:
- bread
@@ -99,4 +97,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/pate_brise.yaml b/culinary/recipes/pate_brise.yaml
index dadd067..93391ff 100644
--- a/culinary/recipes/pate_brise.yaml
+++ b/culinary/recipes/pate_brise.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: pate_brise
-revision: 1
-status: draft
title: Pâte Brisée
categories:
- pastry
@@ -86,4 +84,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/peanut_butter_cookie.yaml b/culinary/recipes/peanut_butter_cookie.yaml
index 9f95d8b..47998e3 100644
--- a/culinary/recipes/peanut_butter_cookie.yaml
+++ b/culinary/recipes/peanut_butter_cookie.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: peanut_butter_cookie
-revision: 1
-status: draft
title: Peanut Butter Cookie
categories:
- dessert
@@ -127,4 +125,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/pesto.yaml b/culinary/recipes/pesto.yaml
index 5984202..aad5880 100644
--- a/culinary/recipes/pesto.yaml
+++ b/culinary/recipes/pesto.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: pesto
-revision: 1
-status: draft
title: Pesto
categories:
- sauce
@@ -95,4 +93,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/philly_steak.yaml b/culinary/recipes/philly_steak.yaml
index f5eafd1..43c35c4 100644
--- a/culinary/recipes/philly_steak.yaml
+++ b/culinary/recipes/philly_steak.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: philly_steak
-revision: 1
-status: draft
title: Philly Steak
categories:
- meat
@@ -139,4 +137,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/pie_quiche_crust.yaml b/culinary/recipes/pie_quiche_crust.yaml
index 49d5f1d..e664914 100644
--- a/culinary/recipes/pie_quiche_crust.yaml
+++ b/culinary/recipes/pie_quiche_crust.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: pie_quiche_crust
-revision: 1
-status: draft
title: Pie/Quiche Crust
categories:
- pastry
@@ -113,4 +111,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/pineapple_salsa.yaml b/culinary/recipes/pineapple_salsa.yaml
index ec9565c..209fe5e 100644
--- a/culinary/recipes/pineapple_salsa.yaml
+++ b/culinary/recipes/pineapple_salsa.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: pineapple_salsa
-revision: 1
-status: draft
title: Pineapple Salsa
categories:
- sauce
@@ -93,4 +91,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/pistachio_shortbread_cookie.yaml b/culinary/recipes/pistachio_shortbread_cookie.yaml
index 49e9ce9..ff8fb74 100644
--- a/culinary/recipes/pistachio_shortbread_cookie.yaml
+++ b/culinary/recipes/pistachio_shortbread_cookie.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: pistachio_shortbread_cookie
-revision: 1
-status: draft
title: Pistachio Shortbread Cookie
categories:
- dessert
@@ -129,4 +127,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/pita.yaml b/culinary/recipes/pita.yaml
index 607e758..13c19bd 100644
--- a/culinary/recipes/pita.yaml
+++ b/culinary/recipes/pita.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: pita
-revision: 1
-status: draft
title: Pita
categories:
- bread
@@ -111,4 +109,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/pizza_sauce.yaml b/culinary/recipes/pizza_sauce.yaml
index 43331f7..1280cad 100644
--- a/culinary/recipes/pizza_sauce.yaml
+++ b/culinary/recipes/pizza_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: pizza_sauce
-revision: 1
-status: draft
title: Pizza Sauce
categories:
- sauce
@@ -114,4 +112,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/popeyes_coater_mix.yaml b/culinary/recipes/popeyes_coater_mix.yaml
index d84cd07..fb3a81b 100644
--- a/culinary/recipes/popeyes_coater_mix.yaml
+++ b/culinary/recipes/popeyes_coater_mix.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: popeyes_coater_mix
-revision: 1
-status: draft
title: Popeyes Coater Mix
categories:
- component
@@ -63,4 +61,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/popeyes_fry_batter.yaml b/culinary/recipes/popeyes_fry_batter.yaml
index fa49349..523be6a 100644
--- a/culinary/recipes/popeyes_fry_batter.yaml
+++ b/culinary/recipes/popeyes_fry_batter.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: popeyes_fry_batter
-revision: 1
-status: draft
title: Popeyes Fry Batter
categories:
- component
@@ -156,4 +154,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/pub_pretzel.yaml b/culinary/recipes/pub_pretzel.yaml
index a3b7d9b..9932976 100644
--- a/culinary/recipes/pub_pretzel.yaml
+++ b/culinary/recipes/pub_pretzel.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: pub_pretzel
-revision: 1
-status: draft
title: Pub Pretzel
categories:
- bread
@@ -129,4 +127,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/pullman_white.yaml b/culinary/recipes/pullman_white.yaml
index fb24422..b81e2c9 100644
--- a/culinary/recipes/pullman_white.yaml
+++ b/culinary/recipes/pullman_white.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: pullman_white
-revision: 1
-status: draft
title: Pullman White
categories:
- bread
@@ -130,4 +128,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/pumpkin_bread.yaml b/culinary/recipes/pumpkin_bread.yaml
index 4a53c2c..7af71ad 100644
--- a/culinary/recipes/pumpkin_bread.yaml
+++ b/culinary/recipes/pumpkin_bread.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: pumpkin_bread
-revision: 1
-status: draft
title: Pumpkin Bread
categories:
- dessert
@@ -79,4 +77,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/pumpkin_ganache.yaml b/culinary/recipes/pumpkin_ganache.yaml
index 75d1971..52228fd 100644
--- a/culinary/recipes/pumpkin_ganache.yaml
+++ b/culinary/recipes/pumpkin_ganache.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: pumpkin_ganache
-revision: 1
-status: draft
title: Pumpkin Ganache
categories:
- sauce
@@ -156,4 +154,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/pumpkin_muffin.yaml b/culinary/recipes/pumpkin_muffin.yaml
index bf1b479..7cb3fa6 100644
--- a/culinary/recipes/pumpkin_muffin.yaml
+++ b/culinary/recipes/pumpkin_muffin.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: pumpkin_muffin
-revision: 1
-status: draft
title: Pumpkin Muffin
categories:
- dessert
@@ -171,4 +169,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/puppy_chow.yaml b/culinary/recipes/puppy_chow.yaml
index fc136a6..62a2542 100644
--- a/culinary/recipes/puppy_chow.yaml
+++ b/culinary/recipes/puppy_chow.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: puppy_chow
-revision: 1
-status: draft
title: Puppy Chow
categories:
- dessert
@@ -116,4 +114,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/quiche_custard.yaml b/culinary/recipes/quiche_custard.yaml
index eb9240f..cf23c12 100644
--- a/culinary/recipes/quiche_custard.yaml
+++ b/culinary/recipes/quiche_custard.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: quiche_custard
-revision: 1
-status: draft
title: Quiche Custard
categories:
- component
@@ -106,4 +104,9 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
+- >-
+ For 12 standard muffin wells in a nonstick pan, use about 40 oz of custard
+ batter and about 16 fl oz of vegetables or other fillings. Set the muffin pan
+ in a half-size sheet pan to make a bain-marie, then pour boiling water into
+ the sheet pan. Bake at 275°F for at least 45 minutes.
diff --git a/culinary/recipes/raising_canes_sauce.yaml b/culinary/recipes/raising_canes_sauce.yaml
index e720da2..d3f769f 100644
--- a/culinary/recipes/raising_canes_sauce.yaml
+++ b/culinary/recipes/raising_canes_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: raising_canes_sauce
-revision: 1
-status: draft
title: Raising Cane's Sauce
categories:
- sauce
@@ -80,4 +78,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/ranch_dressing.yaml b/culinary/recipes/ranch_dressing.yaml
index 0470cfa..2ea3c50 100644
--- a/culinary/recipes/ranch_dressing.yaml
+++ b/culinary/recipes/ranch_dressing.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: ranch_dressing
-revision: 1
-status: draft
title: Ranch Dressing
categories:
- sauce
@@ -52,4 +50,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/ravioli_filling.yaml b/culinary/recipes/ravioli_filling.yaml
index 73dcb92..df9bce6 100644
--- a/culinary/recipes/ravioli_filling.yaml
+++ b/culinary/recipes/ravioli_filling.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: ravioli_filling
-revision: 1
-status: draft
title: Ravioli Filling
categories:
- meat
@@ -113,4 +111,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/reeces_peanut_butter_cup_filling.yaml b/culinary/recipes/reeces_peanut_butter_cup_filling.yaml
index 65995fc..21a8b18 100644
--- a/culinary/recipes/reeces_peanut_butter_cup_filling.yaml
+++ b/culinary/recipes/reeces_peanut_butter_cup_filling.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: reeces_peanut_butter_cup_filling
-revision: 1
-status: draft
title: Reese's Peanut Butter Cup Filling
categories:
- sauce
@@ -53,4 +51,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/refried_beans.yaml b/culinary/recipes/refried_beans.yaml
index 85956bc..44cfc36 100644
--- a/culinary/recipes/refried_beans.yaml
+++ b/culinary/recipes/refried_beans.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: refried_beans
-revision: 1
-status: draft
title: Refried Beans
categories:
- side
@@ -91,4 +89,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/richs_classic_white_icing.yaml b/culinary/recipes/richs_classic_white_icing.yaml
index a344b04..43fabbe 100644
--- a/culinary/recipes/richs_classic_white_icing.yaml
+++ b/culinary/recipes/richs_classic_white_icing.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: richs_classic_white_icing
-revision: 1
-status: draft
title: Rich's Classic White Icing
categories:
- sauce
@@ -67,4 +65,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/richs_maple_icing.yaml b/culinary/recipes/richs_maple_icing.yaml
index 43cd7a7..9811726 100644
--- a/culinary/recipes/richs_maple_icing.yaml
+++ b/culinary/recipes/richs_maple_icing.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: richs_maple_icing
-revision: 1
-status: draft
title: Rich's Maple Icing
categories:
- sauce
@@ -88,4 +86,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/roasted_sweet_potato_carrot.yaml b/culinary/recipes/roasted_sweet_potato_carrot.yaml
index 555a380..5d32a16 100644
--- a/culinary/recipes/roasted_sweet_potato_carrot.yaml
+++ b/culinary/recipes/roasted_sweet_potato_carrot.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: roasted_sweet_potato_carrot
-revision: 1
-status: draft
title: Roasted Sweet Potato and Carrot
categories:
- side
@@ -93,4 +91,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/scrambled_egg_patty.yaml b/culinary/recipes/scrambled_egg_patty.yaml
index 5cd2972..4cb83de 100644
--- a/culinary/recipes/scrambled_egg_patty.yaml
+++ b/culinary/recipes/scrambled_egg_patty.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: scrambled_egg_patty
-revision: 1
-status: draft
title: Scrambled Egg Patty
categories:
- breakfast
@@ -87,4 +85,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/sea_vinaigrette.yaml b/culinary/recipes/sea_vinaigrette.yaml
index 9923f78..507cc32 100644
--- a/culinary/recipes/sea_vinaigrette.yaml
+++ b/culinary/recipes/sea_vinaigrette.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: sea_vinaigrette
-revision: 1
-status: draft
title: Southeast Asian Vinaigrette
categories:
- sauce
@@ -81,4 +79,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/seasoned_chicken.yaml b/culinary/recipes/seasoned_chicken.yaml
index 2992feb..e967369 100644
--- a/culinary/recipes/seasoned_chicken.yaml
+++ b/culinary/recipes/seasoned_chicken.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: seasoned_chicken
-revision: 1
-status: draft
title: Seasoned Chicken
categories:
- meat
@@ -100,4 +98,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/shake_shack_shacksauce.yaml b/culinary/recipes/shake_shack_shacksauce.yaml
index 1445cb0..3e2711a 100644
--- a/culinary/recipes/shake_shack_shacksauce.yaml
+++ b/culinary/recipes/shake_shack_shacksauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: shake_shack_shacksauce
-revision: 1
-status: draft
title: Shake Shack ShackSauce
categories:
- sauce
@@ -68,4 +66,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/shakespeares_pizza_dough.yaml b/culinary/recipes/shakespeares_pizza_dough.yaml
index 293f436..988fb47 100644
--- a/culinary/recipes/shakespeares_pizza_dough.yaml
+++ b/culinary/recipes/shakespeares_pizza_dough.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: shakespeares_pizza_dough
-revision: 1
-status: draft
title: Shakespeare's Pizza Dough
categories:
- bread
@@ -97,4 +95,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/shakespeares_pizza_sauce.yaml b/culinary/recipes/shakespeares_pizza_sauce.yaml
index abac7b3..c0eee67 100644
--- a/culinary/recipes/shakespeares_pizza_sauce.yaml
+++ b/culinary/recipes/shakespeares_pizza_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: shakespeares_pizza_sauce
-revision: 1
-status: draft
title: Shakespeare's Pizza Sauce
categories:
- sauce
@@ -102,4 +100,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/sour_cream.yaml b/culinary/recipes/sour_cream.yaml
index f0a725a..b9a7656 100644
--- a/culinary/recipes/sour_cream.yaml
+++ b/culinary/recipes/sour_cream.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: sour_cream
-revision: 1
-status: draft
title: Sour Cream
categories:
- component
@@ -51,4 +49,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/sourdough.yaml b/culinary/recipes/sourdough.yaml
index 927b360..4a24356 100644
--- a/culinary/recipes/sourdough.yaml
+++ b/culinary/recipes/sourdough.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: sourdough
-revision: 1
-status: draft
title: Sourdough
categories:
- bread
@@ -161,4 +159,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/sourdough_starter.yaml b/culinary/recipes/sourdough_starter.yaml
index 47a01ab..b5905be 100644
--- a/culinary/recipes/sourdough_starter.yaml
+++ b/culinary/recipes/sourdough_starter.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: sourdough_starter
-revision: 1
-status: active
title: Sourdough Starter, 100% Hydration
categories:
- component
diff --git a/culinary/recipes/spritz_cookie.yaml b/culinary/recipes/spritz_cookie.yaml
index 71656a7..7f1d97a 100644
--- a/culinary/recipes/spritz_cookie.yaml
+++ b/culinary/recipes/spritz_cookie.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: spritz_cookie
-revision: 1
-status: draft
title: Spritz Cookie
categories:
- dessert
@@ -123,4 +121,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/srirancha.yaml b/culinary/recipes/srirancha.yaml
index d49a7de..025ed07 100644
--- a/culinary/recipes/srirancha.yaml
+++ b/culinary/recipes/srirancha.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: srirancha
-revision: 1
-status: draft
title: Srirancha
categories:
- sauce
@@ -59,4 +57,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/starch_glaze.yaml b/culinary/recipes/starch_glaze.yaml
index 5d0662e..15220db 100644
--- a/culinary/recipes/starch_glaze.yaml
+++ b/culinary/recipes/starch_glaze.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: starch_glaze
-revision: 1
-status: draft
title: Starch Glaze
categories:
- component
@@ -57,4 +55,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/steamed_eggs.yaml b/culinary/recipes/steamed_eggs.yaml
index b4bc469..44b4a72 100644
--- a/culinary/recipes/steamed_eggs.yaml
+++ b/culinary/recipes/steamed_eggs.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: steamed_eggs
-revision: 1
-status: draft
title: Steamed Eggs
categories:
- breakfast
@@ -82,4 +80,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/subway_italian.yaml b/culinary/recipes/subway_italian.yaml
index af4828c..f052b30 100644
--- a/culinary/recipes/subway_italian.yaml
+++ b/culinary/recipes/subway_italian.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: subway_italian
-revision: 1
-status: draft
title: Subway Italian
categories:
- bread
@@ -148,4 +146,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/subway_whole_wheat.yaml b/culinary/recipes/subway_whole_wheat.yaml
index 32bc2c3..7c6b9c7 100644
--- a/culinary/recipes/subway_whole_wheat.yaml
+++ b/culinary/recipes/subway_whole_wheat.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: subway_whole_wheat
-revision: 1
-status: draft
title: Subway Whole Wheat
categories:
- bread
@@ -157,4 +155,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/sushi_rice.yaml b/culinary/recipes/sushi_rice.yaml
index 5c4f533..608de58 100644
--- a/culinary/recipes/sushi_rice.yaml
+++ b/culinary/recipes/sushi_rice.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: sushi_rice
-revision: 1
-status: draft
title: Sushi Rice
categories:
- side
@@ -82,4 +80,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/sweet_hawaiian_rolls.yaml b/culinary/recipes/sweet_hawaiian_rolls.yaml
index e09f9da..537e588 100644
--- a/culinary/recipes/sweet_hawaiian_rolls.yaml
+++ b/culinary/recipes/sweet_hawaiian_rolls.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: sweet_hawaiian_rolls
-revision: 1
-status: draft
title: Sweet Hawaiian Rolls
categories:
- bread
@@ -145,4 +143,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/sweet_potato_hummus.yaml b/culinary/recipes/sweet_potato_hummus.yaml
index d965bf8..b34c325 100644
--- a/culinary/recipes/sweet_potato_hummus.yaml
+++ b/culinary/recipes/sweet_potato_hummus.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: sweet_potato_hummus
-revision: 1
-status: draft
title: Sweet Potato Hummus
categories:
- side
@@ -101,4 +99,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/sweet_roll.yaml b/culinary/recipes/sweet_roll.yaml
index d542e15..7004688 100644
--- a/culinary/recipes/sweet_roll.yaml
+++ b/culinary/recipes/sweet_roll.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: sweet_roll
-revision: 1
-status: draft
title: Sweet Roll
categories:
- bread
@@ -86,4 +84,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/sweet_sour_sauce.yaml b/culinary/recipes/sweet_sour_sauce.yaml
index 36bee7a..be20ceb 100644
--- a/culinary/recipes/sweet_sour_sauce.yaml
+++ b/culinary/recipes/sweet_sour_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: sweet_sour_sauce
-revision: 1
-status: draft
title: Sweet & Sour Sauce
categories:
- sauce
@@ -79,4 +77,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/taco_bell_refried_beans.yaml b/culinary/recipes/taco_bell_refried_beans.yaml
index 8aeafcf..7fb2005 100644
--- a/culinary/recipes/taco_bell_refried_beans.yaml
+++ b/culinary/recipes/taco_bell_refried_beans.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: taco_bell_refried_beans
-revision: 1
-status: draft
title: Taco Bell Refried Beans
categories:
- side
@@ -86,4 +84,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/taco_bell_seasoned_beef.yaml b/culinary/recipes/taco_bell_seasoned_beef.yaml
index 683b2d9..17d11a2 100644
--- a/culinary/recipes/taco_bell_seasoned_beef.yaml
+++ b/culinary/recipes/taco_bell_seasoned_beef.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: taco_bell_seasoned_beef
-revision: 1
-status: draft
title: Taco Bell Seasoned Beef
categories:
- meat
@@ -131,4 +129,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/taco_bell_slow_roasted_shredded_chicken.yaml b/culinary/recipes/taco_bell_slow_roasted_shredded_chicken.yaml
index b626ffd..35dccb2 100644
--- a/culinary/recipes/taco_bell_slow_roasted_shredded_chicken.yaml
+++ b/culinary/recipes/taco_bell_slow_roasted_shredded_chicken.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: taco_bell_slow_roasted_shredded_chicken
-revision: 1
-status: draft
title: Taco Bell Slow Roasted Shredded Chicken
categories:
- meat
@@ -129,4 +127,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/tangzhong.yaml b/culinary/recipes/tangzhong.yaml
index b2d1c18..7b56dd0 100644
--- a/culinary/recipes/tangzhong.yaml
+++ b/culinary/recipes/tangzhong.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: tangzhong
-revision: 1
-status: active
title: Tangzhong
categories: [component]
tags: [bread, preferment]
diff --git a/culinary/recipes/texas_roadhouse_honey_butter.yaml b/culinary/recipes/texas_roadhouse_honey_butter.yaml
index 1fcc07c..c851762 100644
--- a/culinary/recipes/texas_roadhouse_honey_butter.yaml
+++ b/culinary/recipes/texas_roadhouse_honey_butter.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: texas_roadhouse_honey_butter
-revision: 1
-status: draft
title: Texas Roadhouse Honey Butter
categories:
- sauce
@@ -68,4 +66,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/top_pot_chocolate_icing.yaml b/culinary/recipes/top_pot_chocolate_icing.yaml
index 90c88de..5ebfcf6 100644
--- a/culinary/recipes/top_pot_chocolate_icing.yaml
+++ b/culinary/recipes/top_pot_chocolate_icing.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: top_pot_chocolate_icing
-revision: 1
-status: draft
title: Top Pot Chocolate Icing
categories:
- sauce
@@ -90,4 +88,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/tortilla.yaml b/culinary/recipes/tortilla.yaml
index a9a95bf..1eef5f2 100644
--- a/culinary/recipes/tortilla.yaml
+++ b/culinary/recipes/tortilla.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: tortilla
-revision: 1
-status: draft
title: Tortilla
categories:
- bread
@@ -106,4 +104,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/turkish_herb_sauce.yaml b/culinary/recipes/turkish_herb_sauce.yaml
index efdc114..059202d 100644
--- a/culinary/recipes/turkish_herb_sauce.yaml
+++ b/culinary/recipes/turkish_herb_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: turkish_herb_sauce
-revision: 1
-status: draft
title: Turkish Herb Sauce
categories:
- sauce
@@ -114,4 +112,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/udon_noodle_sauce.yaml b/culinary/recipes/udon_noodle_sauce.yaml
index 709779b..8a81ddd 100644
--- a/culinary/recipes/udon_noodle_sauce.yaml
+++ b/culinary/recipes/udon_noodle_sauce.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: udon_noodle_sauce
-revision: 1
-status: draft
title: Udon Noodle Sauce
categories:
- soup
@@ -87,4 +85,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/waffles.yaml b/culinary/recipes/waffles.yaml
index 3579335..512b2b2 100644
--- a/culinary/recipes/waffles.yaml
+++ b/culinary/recipes/waffles.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: waffles
-revision: 1
-status: draft
title: Waffles
categories:
- breakfast
@@ -118,4 +116,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/whipped_cream.yaml b/culinary/recipes/whipped_cream.yaml
index 6211b69..2bd10c5 100644
--- a/culinary/recipes/whipped_cream.yaml
+++ b/culinary/recipes/whipped_cream.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: whipped_cream
-revision: 1
-status: draft
title: Whipped Cream
categories:
- sauce
@@ -86,4 +84,4 @@ steps:
component_ids:
- main
notes:
-- Formula uses a nominal 100 g basis; review yield and revision before activation.
+- Formula uses a nominal 100 g basis; review the yield before use.
diff --git a/culinary/recipes/white_cheddar_parmesan_blend.yaml b/culinary/recipes/white_cheddar_parmesan_blend.yaml
index fdd1aef..a7d61cb 100644
--- a/culinary/recipes/white_cheddar_parmesan_blend.yaml
+++ b/culinary/recipes/white_cheddar_parmesan_blend.yaml
@@ -1,7 +1,5 @@
schema_version: 2
id: white_cheddar_parmesan_blend
-revision: 1
-status: active
title: White Cheddar–Parmesan Blend
categories:
- component
diff --git a/docs/culinary-data-model.md b/docs/culinary-data-model.md
index 21c1ad5..eed6006 100644
--- a/docs/culinary-data-model.md
+++ b/docs/culinary-data-model.md
@@ -7,10 +7,9 @@ cleanly to relational tables while remaining portable, reviewable YAML. Astro is
a presentation consumer only. It must not become the authority for quantities,
conversions, nutrition, allergens, purchasing, or calculated values.
-`schema_version` describes a document's data contract. A recipe's `revision`
-independently describes changes to that recipe. Names used for search or display
-belong in ingredient `aliases`; canonical references always use stable entity
-IDs.
+`schema_version` describes a document's data contract. Recipes represent their
+current canonical state. Names used for search or display belong in ingredient
+`aliases`; canonical references always use stable entity IDs.
## Canonical and derived boundaries
@@ -20,8 +19,8 @@ and price observations. Projections may later be generated for another
application or database, but they are never canonical.
Derived recipe records contain reproducible nutrition, allergen rollups, and
-costs. They identify the recipe revision, calculation version, calculation
-time, and an input fingerprint. Derived values are disposable and must never
+costs. They identify the recipe, calculation version, calculation time, and an
+input fingerprint. Derived values are disposable and must never
be copied back into canonical source fields as though they were observations.
## Entity model
@@ -31,7 +30,7 @@ entities:
| Entity | Main relationships |
| --- | --- |
-| Recipe | revision; components; ordered lines and steps; ingredients or sub-recipes |
+| Recipe | components; ordered lines and steps; ingredients or sub-recipes |
| Ingredient | aliases; sourced density/measure observations; nutrition/allergen mappings |
| Unit | dimension and conversion to a base unit within that dimension |
| Prep action | optional default edible-yield factor |
@@ -43,7 +42,7 @@ entities:
| Derived recipe | calculated cost, nutrition, allergens, completeness, and warnings |
Recipe components, component lines, and preparation steps are embedded because
-they form a recipe revision aggregate and are edited together. Reusable facts
+they form a recipe aggregate and are edited together. Reusable facts
remain independent records referenced by stable IDs.
Equipment is a reusable, vendor-neutral entity. A recipe may declare equipment
@@ -122,12 +121,12 @@ The USDA API key must never be stored in the repository. Future import tooling
should propose candidates, cache source payloads or normalized facts with their
retrieval dates, and require review before a mapping becomes authoritative.
-## Canonical status
+## Canonical storage
SQLite is the canonical application store. The files in `culinary/` are a
portable import/export dataset and initial seed, not a second writable source of
-truth. Recipes without authored instructions contain one explicit TODO step and
-remain drafts. Formula-only conversions use a nominal 100 g basis and a
+truth. Recipes without authored instructions contain one explicit TODO step.
+Formula-only conversions use a nominal 100 g basis and a
theoretical yield until those values are replaced by observed production data.
Astro reads a generated, read-only SQLite projection and produces static recipe
diff --git a/docs/local-application.md b/docs/local-application.md
index 105f14c..b98f8e9 100644
--- a/docs/local-application.md
+++ b/docs/local-application.md
@@ -5,29 +5,24 @@ portable import/export format, but normal application saves do not modify it.
Derived nutrition and cost are still calculated rather than stored.
Create the initial database from the current portable dataset with Node 22 or
-newer, then run the site and application:
+newer, then run either application mode:
```sh
npm run db:reset
-npm run dev:site
+npm run dev:readonly
npm run dev:app
```
-`npm run site:project` writes `generated/site-projection.json`. Site development,
-checks, and builds run it automatically. Successful application edits refresh
-the same file, allowing the local Astro site to hot-reload database changes while
-remaining read-only.
+Read-only mode serves the same application with SQLite opened read-only, removes
+editing controls, and rejects modifying HTTP requests. Browser-side scaling,
+unit conversion, nutrition, and costing calculations remain available.
The database is written to `var/recipe-book.sqlite` and is intentionally ignored
-by Git. Numbered SQL migrations in `migrations/` define the durable relational
-schema. Run `npm run db:migrate` to upgrade an existing database without
-re-importing or deleting its data. Writable application connections also apply
-pending migrations automatically. The `/app/` dashboard is available in
-development mode. Recipe metadata and yield edits are transactional, increment
-the recipe revision, retain the previous state in `recipe_revisions`, and reject
-saves from stale browser tabs. Portable exports are a separate backup and
-interchange workflow, not part of normal editing.
+by Git. `migrations/001_initial.sql` defines the complete relational schema.
+The application does not support upgrading databases from older schemas: rebuild
+from portable data with `npm run db:reset`. Recipe edits are transactional and a
+private save token prevents stale browser tabs from overwriting newer changes.
+There is no recipe revision history.
-`npm run db:sync` is a compatibility alias for the safe migration command.
-`npm run db:import:yaml` (or `db:reset`) replaces the database from YAML and is
-only intended for initial setup or an explicit restore.
+`npm run db:import:yaml` and `npm run db:reset` both replace the database from
+portable data and are intended for initial setup or an explicit restore.
diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml
index 5939fdb..58a9ead 100644
--- a/k8s/deployment.yaml
+++ b/k8s/deployment.yaml
@@ -25,15 +25,15 @@ spec:
- name: gitea-registry
containers:
- name: recipe-book
- image: git.uuard.com/nicholas/recipe-book
+ image: git.uuard.com/nicholas/formulation
imagePullPolicy: IfNotPresent
ports:
- name: http
- containerPort: 80
+ containerPort: 8080
protocol: TCP
readinessProbe:
httpGet:
- path: /
+ path: /app/
port: http
initialDelaySeconds: 2
periodSeconds: 5
@@ -41,7 +41,7 @@ spec:
failureThreshold: 6
livenessProbe:
httpGet:
- path: /
+ path: /app/
port: http
initialDelaySeconds: 10
periodSeconds: 10
@@ -50,10 +50,10 @@ spec:
resources:
requests:
cpu: 10m
- memory: 32Mi
+ memory: 64Mi
limits:
cpu: 100m
- memory: 128Mi
+ memory: 256Mi
securityContext:
allowPrivilegeEscalation: false
seccompProfile:
diff --git a/k8s/kustomization.yaml b/k8s/kustomization.yaml
index 4eb1d37..c29f5c0 100644
--- a/k8s/kustomization.yaml
+++ b/k8s/kustomization.yaml
@@ -6,5 +6,5 @@ resources:
- service.yaml
- ingress.yaml
images:
- - name: git.uuard.com/nicholas/recipe-book
- newTag: 7c17e3047560967dd58f8f7b8f0dd7387ba46aa5
+ - name: git.uuard.com/nicholas/formulation
+ newTag: "9591742"
diff --git a/migrations/001_initial.sql b/migrations/001_initial.sql
index 867025b..5e6c87b 100644
--- a/migrations/001_initial.sql
+++ b/migrations/001_initial.sql
@@ -1,119 +1,84 @@
PRAGMA foreign_keys = ON;
-CREATE TABLE IF NOT EXISTS schema_migrations (
- version INTEGER PRIMARY KEY,
- name TEXT NOT NULL,
- applied_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
-);
-
CREATE TABLE units (
- id TEXT PRIMARY KEY,
- name TEXT NOT NULL,
- symbol TEXT NOT NULL,
- dimension TEXT NOT NULL,
- system TEXT NOT NULL,
- base_unit_id TEXT REFERENCES units(id),
- factor REAL,
- offset REAL
+ id TEXT PRIMARY KEY, name TEXT NOT NULL, symbol TEXT NOT NULL,
+ dimension TEXT NOT NULL, system TEXT NOT NULL,
+ base_unit_id TEXT REFERENCES units(id), factor REAL, offset REAL
);
CREATE TABLE ingredients (
- id TEXT PRIMARY KEY,
- schema_version INTEGER NOT NULL,
- name TEXT NOT NULL,
- status TEXT NOT NULL,
- categories_json TEXT NOT NULL DEFAULT '[]'
+ id TEXT PRIMARY KEY, schema_version INTEGER NOT NULL, name TEXT NOT NULL,
+ status TEXT NOT NULL, categories_json TEXT NOT NULL DEFAULT '[]',
+ tags_json TEXT NOT NULL DEFAULT '[]', description TEXT,
+ source_json TEXT NOT NULL DEFAULT '{}', deleted_at TEXT
);
CREATE TABLE ingredient_aliases (
ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE,
- name TEXT NOT NULL,
- kind TEXT,
- PRIMARY KEY (ingredient_id, name)
+ name TEXT NOT NULL, kind TEXT, PRIMARY KEY (ingredient_id, name)
);
CREATE TABLE equipment (
- id TEXT PRIMARY KEY,
- name TEXT NOT NULL,
- category TEXT,
- notes TEXT
+ id TEXT PRIMARY KEY, name TEXT NOT NULL, category TEXT, notes TEXT
);
CREATE TABLE prep_actions (
- id TEXT PRIMARY KEY,
- name TEXT NOT NULL,
- action_type TEXT NOT NULL,
- default_yield_factor REAL CHECK(default_yield_factor > 0 AND default_yield_factor <= 1),
- notes TEXT
+ id TEXT PRIMARY KEY, name TEXT NOT NULL, action_type TEXT NOT NULL,
+ default_yield_factor REAL CHECK(default_yield_factor > 0), notes TEXT
);
CREATE TABLE recipes (
- id TEXT PRIMARY KEY,
- schema_version INTEGER NOT NULL,
- revision INTEGER NOT NULL,
- status TEXT NOT NULL,
- title TEXT NOT NULL,
- summary TEXT,
- categories_json TEXT NOT NULL DEFAULT '[]',
- tags_json TEXT NOT NULL DEFAULT '[]',
- yield_quantity REAL NOT NULL,
- yield_unit_id TEXT NOT NULL REFERENCES units(id),
- yield_servings REAL,
- yield_basis TEXT,
- scaling_mode TEXT,
- scaling_basis_id TEXT,
- scaling_basis_quantity REAL,
- scaling_basis_unit_id TEXT REFERENCES units(id),
- notes_json TEXT NOT NULL DEFAULT '[]'
+ id TEXT PRIMARY KEY, schema_version INTEGER NOT NULL,
+ save_version INTEGER NOT NULL DEFAULT 1, title TEXT NOT NULL, summary TEXT,
+ categories_json TEXT NOT NULL DEFAULT '[]', tags_json TEXT NOT NULL DEFAULT '[]',
+ yield_quantity REAL NOT NULL, yield_unit_id TEXT NOT NULL REFERENCES units(id),
+ yield_servings REAL, yield_basis TEXT, scaling_mode TEXT, scaling_basis_id TEXT,
+ scaling_basis_quantity REAL, scaling_basis_unit_id TEXT REFERENCES units(id),
+ notes_json TEXT NOT NULL DEFAULT '[]', source_json TEXT NOT NULL DEFAULT '{}',
+ auto_yield INTEGER NOT NULL DEFAULT 0, station TEXT, deleted_at TEXT,
+ cover_media_url TEXT
);
CREATE TABLE recipe_components (
recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE,
- id TEXT NOT NULL,
- position INTEGER NOT NULL,
- name TEXT NOT NULL,
- notes_json TEXT NOT NULL DEFAULT '[]',
- PRIMARY KEY (recipe_id, id)
+ id TEXT NOT NULL, position INTEGER NOT NULL, name TEXT NOT NULL,
+ notes_json TEXT NOT NULL DEFAULT '[]', PRIMARY KEY (recipe_id, id)
);
CREATE TABLE recipe_items (
- recipe_id TEXT NOT NULL,
- component_id TEXT NOT NULL,
- id TEXT NOT NULL,
- position INTEGER NOT NULL,
- ingredient_id TEXT REFERENCES ingredients(id),
- subrecipe_id TEXT REFERENCES recipes(id),
- subrecipe_revision INTEGER,
- quantity REAL NOT NULL,
- unit_id TEXT NOT NULL REFERENCES units(id),
- percentage REAL,
- basis_member INTEGER NOT NULL DEFAULT 0,
- optional INTEGER NOT NULL DEFAULT 0,
- notes TEXT,
+ recipe_id TEXT NOT NULL, component_id TEXT NOT NULL, id TEXT NOT NULL,
+ position INTEGER NOT NULL, ingredient_id TEXT REFERENCES ingredients(id),
+ subrecipe_id TEXT REFERENCES recipes(id), quantity REAL NOT NULL,
+ unit_id TEXT NOT NULL REFERENCES units(id), percentage REAL,
+ basis_member INTEGER NOT NULL DEFAULT 0, optional INTEGER NOT NULL DEFAULT 0,
+ notes TEXT, nutrition_retention_factor REAL NOT NULL DEFAULT 1
+ CHECK(nutrition_retention_factor >= 0 AND nutrition_retention_factor <= 1),
PRIMARY KEY (recipe_id, id),
- FOREIGN KEY (recipe_id, component_id) REFERENCES recipe_components(recipe_id, id) ON DELETE CASCADE,
+ FOREIGN KEY (recipe_id, component_id)
+ REFERENCES recipe_components(recipe_id, id) ON DELETE CASCADE,
CHECK ((ingredient_id IS NOT NULL) <> (subrecipe_id IS NOT NULL))
);
-CREATE TABLE item_prep_actions (
- recipe_id TEXT NOT NULL,
- item_id TEXT NOT NULL,
- position INTEGER NOT NULL,
+CREATE TABLE ingredient_prep_actions (
+ ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE,
action_id TEXT NOT NULL REFERENCES prep_actions(id),
- yield_factor REAL CHECK(yield_factor > 0 AND yield_factor <= 1),
- notes TEXT,
+ yield_factor REAL NOT NULL CHECK(yield_factor > 0), notes TEXT,
+ PRIMARY KEY (ingredient_id, action_id)
+);
+
+CREATE TABLE item_prep_actions (
+ recipe_id TEXT NOT NULL, item_id TEXT NOT NULL, position INTEGER NOT NULL,
+ action_id TEXT NOT NULL REFERENCES prep_actions(id),
+ yield_factor REAL CHECK(yield_factor > 0), notes TEXT,
PRIMARY KEY (recipe_id, item_id, position),
FOREIGN KEY (recipe_id, item_id) REFERENCES recipe_items(recipe_id, id) ON DELETE CASCADE
);
CREATE TABLE recipe_steps (
recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE,
- id TEXT NOT NULL,
- position INTEGER NOT NULL,
- instruction TEXT NOT NULL,
+ id TEXT NOT NULL, position INTEGER NOT NULL, instruction TEXT NOT NULL,
critical_control_point INTEGER NOT NULL DEFAULT 0,
- PRIMARY KEY (recipe_id, id),
- UNIQUE (recipe_id, position)
+ PRIMARY KEY (recipe_id, id), UNIQUE (recipe_id, position)
);
CREATE TABLE recipe_equipment (
@@ -123,22 +88,41 @@ CREATE TABLE recipe_equipment (
);
CREATE TABLE step_equipment (
- recipe_id TEXT NOT NULL,
- step_id TEXT NOT NULL,
+ recipe_id TEXT NOT NULL, step_id TEXT NOT NULL,
equipment_id TEXT NOT NULL REFERENCES equipment(id),
PRIMARY KEY (recipe_id, step_id, equipment_id),
FOREIGN KEY (recipe_id, step_id) REFERENCES recipe_steps(recipe_id, id) ON DELETE CASCADE
);
+CREATE TABLE ingredient_measure_conversions (
+ ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE,
+ id TEXT NOT NULL, from_quantity REAL NOT NULL,
+ from_unit_id TEXT NOT NULL REFERENCES units(id), to_quantity REAL NOT NULL,
+ to_unit_id TEXT NOT NULL REFERENCES units(id), state TEXT,
+ source_json TEXT NOT NULL, PRIMARY KEY (ingredient_id, id)
+);
+
+CREATE TABLE ingredient_density_measurements (
+ ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE,
+ id TEXT NOT NULL, mass_quantity REAL NOT NULL,
+ mass_unit_id TEXT NOT NULL REFERENCES units(id), volume_quantity REAL NOT NULL,
+ volume_unit_id TEXT NOT NULL REFERENCES units(id), temperature_c REAL,
+ state TEXT, source_json TEXT NOT NULL, PRIMARY KEY (ingredient_id, id)
+);
+
+CREATE TABLE recipe_measure_conversions (
+ recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE,
+ id TEXT NOT NULL, from_quantity REAL NOT NULL CHECK(from_quantity > 0),
+ from_unit_id TEXT NOT NULL REFERENCES units(id),
+ to_quantity REAL NOT NULL CHECK(to_quantity > 0),
+ to_unit_id TEXT NOT NULL REFERENCES units(id), notes TEXT,
+ source_json TEXT NOT NULL DEFAULT '{}', PRIMARY KEY (recipe_id, id)
+);
+
CREATE TABLE purchase_items (
- id TEXT PRIMARY KEY,
- ingredient_id TEXT NOT NULL REFERENCES ingredients(id),
- name TEXT NOT NULL,
- brand TEXT,
- supplier_id TEXT,
- supplier_sku TEXT,
- status TEXT NOT NULL,
- package_quantity REAL NOT NULL,
+ id TEXT PRIMARY KEY, ingredient_id TEXT NOT NULL REFERENCES ingredients(id),
+ name TEXT NOT NULL, brand TEXT, supplier_id TEXT, supplier_sku TEXT,
+ status TEXT NOT NULL, package_quantity REAL NOT NULL,
package_unit_id TEXT NOT NULL REFERENCES units(id),
units_per_case INTEGER NOT NULL DEFAULT 1,
usable_yield_factor REAL NOT NULL DEFAULT 1
@@ -146,24 +130,39 @@ CREATE TABLE purchase_items (
CREATE TABLE price_observations (
purchase_item_id TEXT NOT NULL REFERENCES purchase_items(id) ON DELETE CASCADE,
- effective_at TEXT NOT NULL,
- currency TEXT NOT NULL,
- amount REAL NOT NULL,
+ effective_at TEXT NOT NULL, currency TEXT NOT NULL, amount REAL NOT NULL,
source_json TEXT NOT NULL,
PRIMARY KEY (purchase_item_id, effective_at, currency)
);
CREATE TABLE source_mappings (
- id TEXT PRIMARY KEY,
- subject_type TEXT NOT NULL,
- subject_id TEXT NOT NULL,
- mapping_type TEXT NOT NULL,
- status TEXT NOT NULL,
- source_json TEXT NOT NULL,
- nutrition_json TEXT
+ id TEXT PRIMARY KEY, subject_type TEXT NOT NULL, subject_id TEXT NOT NULL,
+ mapping_type TEXT NOT NULL, status TEXT NOT NULL,
+ source_json TEXT NOT NULL, nutrition_json TEXT
+);
+
+CREATE TABLE collections (
+ id TEXT PRIMARY KEY, name TEXT NOT NULL, description TEXT,
+ source_json TEXT NOT NULL, deleted_at TEXT
+);
+
+CREATE TABLE collection_recipes (
+ collection_id TEXT NOT NULL REFERENCES collections(id) ON DELETE CASCADE,
+ recipe_id TEXT NOT NULL REFERENCES recipes(id), position INTEGER NOT NULL,
+ PRIMARY KEY (collection_id, recipe_id)
+);
+
+CREATE TABLE recipe_media (
+ recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE,
+ id TEXT NOT NULL, step_id TEXT, media_type TEXT NOT NULL
+ CHECK(media_type IN ('image', 'video')),
+ url TEXT NOT NULL, caption TEXT, position INTEGER NOT NULL,
+ PRIMARY KEY (recipe_id, id),
+ FOREIGN KEY (recipe_id, step_id) REFERENCES recipe_steps(recipe_id, id) ON DELETE CASCADE
);
CREATE INDEX recipe_items_ingredient_idx ON recipe_items(ingredient_id);
CREATE INDEX recipe_items_subrecipe_idx ON recipe_items(subrecipe_id);
CREATE INDEX purchase_items_ingredient_idx ON purchase_items(ingredient_id);
CREATE INDEX source_mappings_subject_idx ON source_mappings(subject_type, subject_id);
+CREATE INDEX recipe_media_recipe_idx ON recipe_media(recipe_id, position);
diff --git a/migrations/002_recipe_editing.sql b/migrations/002_recipe_editing.sql
deleted file mode 100644
index fdcf062..0000000
--- a/migrations/002_recipe_editing.sql
+++ /dev/null
@@ -1,10 +0,0 @@
-ALTER TABLE recipes ADD COLUMN source_json TEXT NOT NULL DEFAULT '{}';
-
-CREATE TABLE recipe_revisions (
- recipe_id TEXT NOT NULL,
- revision INTEGER NOT NULL,
- saved_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
- change_summary TEXT NOT NULL,
- snapshot_json TEXT NOT NULL,
- PRIMARY KEY (recipe_id, revision)
-);
diff --git a/migrations/003_ingredient_workspace.sql b/migrations/003_ingredient_workspace.sql
deleted file mode 100644
index b16e69d..0000000
--- a/migrations/003_ingredient_workspace.sql
+++ /dev/null
@@ -1,48 +0,0 @@
-ALTER TABLE ingredients ADD COLUMN source_json TEXT NOT NULL DEFAULT '{}';
-
-CREATE TABLE ingredient_prep_actions (
- ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE,
- action_id TEXT NOT NULL REFERENCES prep_actions(id),
- yield_factor REAL NOT NULL CHECK(yield_factor > 0 AND yield_factor <= 1),
- notes TEXT,
- PRIMARY KEY (ingredient_id, action_id)
-);
-
-CREATE TABLE ingredient_measure_conversions (
- ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE,
- id TEXT NOT NULL,
- from_quantity REAL NOT NULL,
- from_unit_id TEXT NOT NULL REFERENCES units(id),
- to_quantity REAL NOT NULL,
- to_unit_id TEXT NOT NULL REFERENCES units(id),
- state TEXT,
- source_json TEXT NOT NULL,
- PRIMARY KEY (ingredient_id, id)
-);
-
-CREATE TABLE ingredient_density_measurements (
- ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE,
- id TEXT NOT NULL,
- mass_quantity REAL NOT NULL,
- mass_unit_id TEXT NOT NULL REFERENCES units(id),
- volume_quantity REAL NOT NULL,
- volume_unit_id TEXT NOT NULL REFERENCES units(id),
- temperature_c REAL,
- state TEXT,
- source_json TEXT NOT NULL,
- PRIMARY KEY (ingredient_id, id)
-);
-
-CREATE TABLE collections (
- id TEXT PRIMARY KEY,
- name TEXT NOT NULL,
- description TEXT,
- source_json TEXT NOT NULL
-);
-
-CREATE TABLE collection_recipes (
- collection_id TEXT NOT NULL REFERENCES collections(id) ON DELETE CASCADE,
- recipe_id TEXT NOT NULL REFERENCES recipes(id),
- position INTEGER NOT NULL,
- PRIMARY KEY (collection_id, recipe_id)
-);
diff --git a/migrations/004_recipe_measure_conversions.sql b/migrations/004_recipe_measure_conversions.sql
deleted file mode 100644
index 9d6274e..0000000
--- a/migrations/004_recipe_measure_conversions.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-CREATE TABLE recipe_measure_conversions (
- recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE,
- id TEXT NOT NULL,
- from_quantity REAL NOT NULL CHECK (from_quantity > 0),
- from_unit_id TEXT NOT NULL REFERENCES units(id),
- to_quantity REAL NOT NULL CHECK (to_quantity > 0),
- to_unit_id TEXT NOT NULL REFERENCES units(id),
- notes TEXT,
- source_json TEXT NOT NULL DEFAULT '{}',
- PRIMARY KEY (recipe_id, id)
-);
diff --git a/migrations/005_culinary_workflows.sql b/migrations/005_culinary_workflows.sql
deleted file mode 100644
index d681b5a..0000000
--- a/migrations/005_culinary_workflows.sql
+++ /dev/null
@@ -1,21 +0,0 @@
-ALTER TABLE recipe_items ADD COLUMN nutrition_retention_factor REAL NOT NULL DEFAULT 1 CHECK(nutrition_retention_factor >= 0 AND nutrition_retention_factor <= 1);
-ALTER TABLE recipes ADD COLUMN auto_yield INTEGER NOT NULL DEFAULT 0;
-ALTER TABLE recipes ADD COLUMN station TEXT;
-ALTER TABLE recipes ADD COLUMN deleted_at TEXT;
-ALTER TABLE recipes ADD COLUMN cover_media_url TEXT;
-ALTER TABLE ingredients ADD COLUMN deleted_at TEXT;
-ALTER TABLE collections ADD COLUMN deleted_at TEXT;
-
-CREATE TABLE recipe_media (
- recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE,
- id TEXT NOT NULL,
- step_id TEXT,
- media_type TEXT NOT NULL CHECK(media_type IN ('image','video')),
- url TEXT NOT NULL,
- caption TEXT,
- position INTEGER NOT NULL,
- PRIMARY KEY (recipe_id,id),
- FOREIGN KEY (recipe_id,step_id) REFERENCES recipe_steps(recipe_id,id) ON DELETE CASCADE
-);
-
-CREATE INDEX recipe_media_recipe_idx ON recipe_media(recipe_id,position);
diff --git a/migrations/006_allow_prep_yield_gain.sql b/migrations/006_allow_prep_yield_gain.sql
deleted file mode 100644
index 095a8ed..0000000
--- a/migrations/006_allow_prep_yield_gain.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-CREATE TABLE ingredient_prep_actions_new (
- ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE,
- action_id TEXT NOT NULL REFERENCES prep_actions(id),
- yield_factor REAL NOT NULL CHECK(yield_factor > 0),
- notes TEXT,
- PRIMARY KEY (ingredient_id, action_id)
-);
-
-INSERT INTO ingredient_prep_actions_new (ingredient_id, action_id, yield_factor, notes)
-SELECT ingredient_id, action_id, yield_factor, notes
-FROM ingredient_prep_actions;
-
-DROP TABLE ingredient_prep_actions;
-ALTER TABLE ingredient_prep_actions_new RENAME TO ingredient_prep_actions;
diff --git a/migrations/007_ingredient_editor_fields.sql b/migrations/007_ingredient_editor_fields.sql
deleted file mode 100644
index 527d6e8..0000000
--- a/migrations/007_ingredient_editor_fields.sql
+++ /dev/null
@@ -1,10 +0,0 @@
-ALTER TABLE ingredients ADD COLUMN description TEXT;
-ALTER TABLE ingredients ADD COLUMN tags_json TEXT NOT NULL DEFAULT '[]';
-
-UPDATE ingredients
-SET tags_json = categories_json;
-
-UPDATE ingredients
-SET description = json_extract(source_json, '$.description')
-WHERE json_valid(source_json)
- AND json_type(source_json, '$.description') = 'text';
diff --git a/migrations/008_separate_ingredient_tags.sql b/migrations/008_separate_ingredient_tags.sql
deleted file mode 100644
index 0497ad1..0000000
--- a/migrations/008_separate_ingredient_tags.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-UPDATE ingredients
-SET tags_json = '[]'
-WHERE tags_json = categories_json;
diff --git a/package.json b/package.json
index 2cec7b0..f121da4 100644
--- a/package.json
+++ b/package.json
@@ -7,23 +7,18 @@
"npm": ">=9.6.5"
},
"scripts": {
- "dev": "npm run dev:site",
- "dev:site": "npm run site:project && astro dev --config astro.config.mjs --port 4321",
+ "dev": "npm run dev:app",
"dev:app": "astro dev --config astro.app.config.mjs --port 4322",
"restart:app": "node scripts/restart-app.mjs",
- "check": "npm run check:site && npm run check:app",
- "check:site": "npm run site:project && astro check --config astro.config.mjs",
+ "dev:readonly": "FORMULATION_READ_ONLY=true astro dev --config astro.app.config.mjs --port 4399",
+ "check": "npm run check:app",
"check:app": "astro check --config astro.app.config.mjs",
- "build": "npm run build:site && npm run build:app",
- "build:site": "npm run site:project && astro check --config astro.config.mjs && astro build --config astro.config.mjs",
+ "build": "npm run build:app",
"build:app": "astro check --config astro.app.config.mjs && astro build --config astro.app.config.mjs",
- "preview": "npm run preview:site",
- "preview:site": "astro preview --config astro.config.mjs --port 4321",
+ "start": "node dist/app/server/entry.mjs",
+ "start:readonly": "FORMULATION_READ_ONLY=true HOST=127.0.0.1 PORT=4399 node dist/app/server/entry.mjs",
"preview:app": "astro preview --config astro.app.config.mjs --port 4322",
"test": "vitest run",
- "site:project": "node scripts/site-project.mjs",
- "db:sync": "npm run db:migrate",
- "db:migrate": "node scripts/db-migrate.mjs",
"db:reset": "node scripts/db-sync.mjs --reset",
"db:import:yaml": "node scripts/db-sync.mjs --reset"
},
diff --git a/scripts/corpus-export b/scripts/corpus-export
index a6ef06f..0a4736f 100755
--- a/scripts/corpus-export
+++ b/scripts/corpus-export
@@ -47,8 +47,6 @@ def render_recipe(recipe: dict, ingredients: dict[str, dict], recipes: dict[str,
lines.extend(
[
f"Recipe ID: `{recipe['id']}`",
- f"Revision: {recipe['revision']}",
- f"Status: {recipe['status']}",
f"Categories: {', '.join(recipe['categories']) or 'None'}",
f"Tags: {', '.join(recipe['tags']) or 'None'}",
f"Yield: {amount_text(recipe['yield']['amount'])}",
diff --git a/scripts/db-migrate.mjs b/scripts/db-migrate.mjs
deleted file mode 100644
index 43a4df8..0000000
--- a/scripts/db-migrate.mjs
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env node
-import fs from "node:fs";
-import path from "node:path";
-import { DatabaseSync } from "node:sqlite";
-import { applyMigrations } from "./lib/migrations.mjs";
-
-const databasePath = path.resolve(process.cwd(), "var", "recipe-book.sqlite");
-if (!fs.existsSync(databasePath)) throw new Error(`Database does not exist: ${databasePath}. Run npm run db:sync once to import the initial data.`);
-const database = new DatabaseSync(databasePath);
-database.exec("PRAGMA foreign_keys = ON; PRAGMA journal_mode = WAL;");
-try {
- const applied = applyMigrations(database);
- console.log(applied.length ? `Applied ${applied.join(", ")}` : "Database schema is current.");
-} finally {
- database.close();
-}
diff --git a/scripts/db-sync.mjs b/scripts/db-sync.mjs
index a81d489..f93fe78 100644
--- a/scripts/db-sync.mjs
+++ b/scripts/db-sync.mjs
@@ -4,12 +4,11 @@ import path from "node:path";
import process from "node:process";
import { DatabaseSync } from "node:sqlite";
import YAML from "yaml";
-import { applyMigrations } from "./lib/migrations.mjs";
import { writeSiteProjection } from "./lib/site-projection.mjs";
const root = path.resolve(import.meta.dirname, "..");
const databasePath = path.join(root, "var", "recipe-book.sqlite");
-if (!process.argv.includes("--reset")) throw new Error("YAML import replaces the canonical database. Re-run with --reset, or use npm run db:migrate for a safe schema upgrade.");
+if (!process.argv.includes("--reset")) throw new Error("Database initialization replaces the local database. Re-run with --reset.");
if (fs.existsSync(databasePath)) fs.rmSync(databasePath);
fs.mkdirSync(path.dirname(databasePath), { recursive: true });
const db = new DatabaseSync(databasePath);
@@ -23,7 +22,7 @@ const records = (directory) => {
const run = (sql, values) => db.prepare(sql).run(...values);
const json = (value) => JSON.stringify(value ?? []);
-applyMigrations(db, { migrationsDirectory: path.join(root, "migrations") });
+db.exec(fs.readFileSync(path.join(root, "migrations", "001_initial.sql"), "utf8"));
db.exec("BEGIN IMMEDIATE");
try {
@@ -39,13 +38,13 @@ try {
for (const item of records("equipment")) run("INSERT INTO equipment VALUES (?, ?, ?, ?)", [item.id, item.name, item.category ?? null, item.notes ?? null]);
for (const action of records("prep_actions")) run("INSERT INTO prep_actions VALUES (?, ?, ?, ?, ?)", [action.id, action.name, action.action_type, action.default_yield_factor ?? null, action.notes ?? null]);
const recipes = records("recipes");
- for (const recipe of recipes) run("INSERT INTO recipes(id, schema_version, revision, status, title, summary, categories_json, tags_json, yield_quantity, yield_unit_id, yield_servings, yield_basis, scaling_mode, scaling_basis_id, scaling_basis_quantity, scaling_basis_unit_id, notes_json, source_json) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [recipe.id, recipe.schema_version, recipe.revision, recipe.status, recipe.title, recipe.summary ?? null, json(recipe.categories), json(recipe.tags), recipe.yield.amount.quantity, recipe.yield.amount.unit_id, recipe.yield.servings ?? null, recipe.yield.basis ?? null, recipe.scaling?.mode ?? null, recipe.scaling?.basis_id ?? null, recipe.scaling?.basis_amount?.quantity ?? null, recipe.scaling?.basis_amount?.unit_id ?? null, json(recipe.notes), json(recipe)]);
+ for (const recipe of recipes) run("INSERT INTO recipes(id, schema_version, title, summary, categories_json, tags_json, yield_quantity, yield_unit_id, yield_servings, yield_basis, scaling_mode, scaling_basis_id, scaling_basis_quantity, scaling_basis_unit_id, notes_json, source_json) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [recipe.id, recipe.schema_version, recipe.title, recipe.summary ?? null, json(recipe.categories), json(recipe.tags), recipe.yield.amount.quantity, recipe.yield.amount.unit_id, recipe.yield.servings ?? null, recipe.yield.basis ?? null, recipe.scaling?.mode ?? null, recipe.scaling?.basis_id ?? null, recipe.scaling?.basis_amount?.quantity ?? null, recipe.scaling?.basis_amount?.unit_id ?? null, json(recipe.notes), json(recipe)]);
for (const recipe of recipes) {
for (const conversion of recipe.measure_conversions ?? []) run("INSERT INTO recipe_measure_conversions VALUES (?, ?, ?, ?, ?, ?, ?, ?)", [recipe.id, conversion.id, conversion.from.quantity, conversion.from.unit_id, conversion.to.quantity, conversion.to.unit_id, conversion.notes ?? null, json(conversion.source ?? {})]);
for (const [componentPosition, component] of recipe.components.entries()) {
run("INSERT INTO recipe_components VALUES (?, ?, ?, ?, ?)", [recipe.id, component.id, componentPosition + 1, component.name, json(component.notes)]);
for (const [itemPosition, item] of component.items.entries()) {
- run("INSERT INTO recipe_items VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [recipe.id, component.id, item.id, itemPosition + 1, item.reference.ingredient_id ?? null, item.reference.recipe_id ?? null, item.reference.revision ?? null, item.amount.quantity, item.amount.unit_id, item.percentage ?? null, item.basis_member ? 1 : 0, item.optional ? 1 : 0, item.notes ?? null]);
+ run("INSERT INTO recipe_items(recipe_id, component_id, id, position, ingredient_id, subrecipe_id, quantity, unit_id, percentage, basis_member, optional, notes, nutrition_retention_factor) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [recipe.id, component.id, item.id, itemPosition + 1, item.reference.ingredient_id ?? null, item.reference.recipe_id ?? null, item.amount.quantity, item.amount.unit_id, item.percentage ?? null, item.basis_member ? 1 : 0, item.optional ? 1 : 0, item.notes ?? null, item.nutrition_retention_factor ?? 1]);
for (const [prepPosition, prep] of (item.prep ?? []).entries()) run("INSERT INTO item_prep_actions VALUES (?, ?, ?, ?, ?, ?)", [recipe.id, item.id, prepPosition + 1, prep.action_id, prep.yield_factor ?? null, prep.notes ?? null]);
}
}
@@ -67,7 +66,7 @@ try {
}
for (const mapping of records("source_mappings")) run("INSERT INTO source_mappings VALUES (?, ?, ?, ?, ?, ?, ?)", [mapping.id, mapping.subject.type, mapping.subject.id, mapping.mapping_type, mapping.status, json(mapping.source), mapping.nutrition_per_100g ? json(mapping.nutrition_per_100g) : null]);
for (const collection of records("collections")) {
- run("INSERT INTO collections VALUES (?, ?, ?, ?)", [collection.id, collection.name, collection.description ?? null, json(collection)]);
+ run("INSERT INTO collections(id, name, description, source_json) VALUES (?, ?, ?, ?)", [collection.id, collection.name, collection.description ?? null, json(collection)]);
for (const [position, entry] of (collection.entries ?? []).entries()) run("INSERT INTO collection_recipes VALUES (?, ?, ?)", [collection.id, entry.recipe_id, position + 1]);
}
db.exec("COMMIT");
diff --git a/scripts/lib/migrations.d.mts b/scripts/lib/migrations.d.mts
deleted file mode 100644
index 5aaf201..0000000
--- a/scripts/lib/migrations.d.mts
+++ /dev/null
@@ -1,3 +0,0 @@
-import type { DatabaseSync } from "node:sqlite";
-
-export function applyMigrations(database: DatabaseSync, options?: { migrationsDirectory?: string }): string[];
diff --git a/scripts/lib/migrations.mjs b/scripts/lib/migrations.mjs
deleted file mode 100644
index 8aa6904..0000000
--- a/scripts/lib/migrations.mjs
+++ /dev/null
@@ -1,24 +0,0 @@
-import fs from "node:fs";
-import path from "node:path";
-
-export function applyMigrations(database, options = {}) {
- const migrationsDirectory = options.migrationsDirectory ?? path.resolve(process.cwd(), "migrations");
- const names = fs.readdirSync(migrationsDirectory).filter((name) => /^\d+.*\.sql$/.test(name)).sort((left, right) => Number(left.match(/^\d+/)[0]) - Number(right.match(/^\d+/)[0]));
- database.exec("CREATE TABLE IF NOT EXISTS schema_migrations (version INTEGER PRIMARY KEY, name TEXT NOT NULL, applied_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP)");
- const applied = [];
- for (const name of names) {
- const version = Number(name.match(/^\d+/)[0]);
- if (database.prepare("SELECT 1 FROM schema_migrations WHERE version = ?").get(version)) continue;
- database.exec("BEGIN IMMEDIATE");
- try {
- database.exec(fs.readFileSync(path.join(migrationsDirectory, name), "utf8"));
- database.prepare("INSERT INTO schema_migrations(version, name) VALUES (?, ?)").run(version, name);
- database.exec("COMMIT");
- applied.push(name);
- } catch (error) {
- database.exec("ROLLBACK");
- throw new Error(`Failed database migration ${name}`, { cause: error });
- }
- }
- return applied;
-}
diff --git a/scripts/lib/site-projection.mjs b/scripts/lib/site-projection.mjs
index 6252b59..d87f77c 100644
--- a/scripts/lib/site-projection.mjs
+++ b/scripts/lib/site-projection.mjs
@@ -34,12 +34,12 @@ export function createSiteProjection(database) {
const recipeConversionQuery=database.prepare("SELECT * FROM recipe_measure_conversions WHERE recipe_id=? ORDER BY id");
const recipes = database.prepare("SELECT * FROM recipes ORDER BY id").all().map((row)=>{
const source=json(row.source_json,{}), oldComponents=new Map((source.components??[]).map((value)=>[value.id,value])), oldSteps=new Map((source.steps??[]).map((value)=>[value.id,value]));
- const components=componentQuery.all(row.id).map((component)=>{const old=oldComponents.get(component.id)??{};return {...old,id:component.id,name:component.name,notes:json(component.notes_json,[]),items:itemQuery.all(row.id,component.id).map((item)=>({id:item.id,reference:item.ingredient_id?{ingredient_id:item.ingredient_id}:{recipe_id:item.subrecipe_id,...(item.subrecipe_revision!=null?{revision:item.subrecipe_revision}:{})},amount:{quantity:item.quantity,unit_id:item.unit_id},...(item.percentage!=null?{percentage:item.percentage}:{}),...(item.basis_member?{basis_member:true}:{}),...(item.optional?{optional:true}:{}),...(item.notes?{notes:item.notes}:{}),...(item.nutrition_retention_factor!==1?{nutrition_retention_factor:item.nutrition_retention_factor}:{}),...(itemPrepQuery.all(row.id,item.id).length?{prep:itemPrepQuery.all(row.id,item.id).map((prep)=>({action_id:prep.action_id,...(prep.yield_factor!=null?{yield_factor:prep.yield_factor}:{}),...(prep.notes?{notes:prep.notes}:{})}))}:{})}))};});
+ const components=componentQuery.all(row.id).map((component)=>{const old=oldComponents.get(component.id)??{};return {...old,id:component.id,name:component.name,notes:json(component.notes_json,[]),items:itemQuery.all(row.id,component.id).map((item)=>({id:item.id,reference:item.ingredient_id?{ingredient_id:item.ingredient_id}:{recipe_id:item.subrecipe_id},amount:{quantity:item.quantity,unit_id:item.unit_id},...(item.percentage!=null?{percentage:item.percentage}:{}),...(item.basis_member?{basis_member:true}:{}),...(item.optional?{optional:true}:{}),...(item.notes?{notes:item.notes}:{}),...(item.nutrition_retention_factor!==1?{nutrition_retention_factor:item.nutrition_retention_factor}:{}),...(itemPrepQuery.all(row.id,item.id).length?{prep:itemPrepQuery.all(row.id,item.id).map((prep)=>({action_id:prep.action_id,...(prep.yield_factor!=null?{yield_factor:prep.yield_factor}:{}),...(prep.notes?{notes:prep.notes}:{})}))}:{})}))};});
const steps=stepQuery.all(row.id).map((step,index)=>{const old=oldSteps.get(step.id)??{},equipment_ids=stepEquipmentQuery.all(row.id,step.id).map((value)=>value.equipment_id);return {...old,id:step.id,order:index+1,instruction:step.instruction,...(step.critical_control_point?{critical_control_point:true}:{}),...(equipment_ids.length?{equipment_ids}:{})};});
const equipment_ids=recipeEquipmentQuery.all(row.id).map((value)=>value.equipment_id);
source.measure_conversions=recipeConversionQuery.all(row.id).map((value)=>({id:value.id,from:{quantity:value.from_quantity,unit_id:value.from_unit_id},to:{quantity:value.to_quantity,unit_id:value.to_unit_id},...(value.notes?{notes:value.notes}:{}),source:json(value.source_json,{})}));
const scaling=row.scaling_mode?{mode:row.scaling_mode,...(row.scaling_basis_id?{basis_id:row.scaling_basis_id}:{}),...(row.scaling_basis_quantity!=null&&row.scaling_basis_unit_id?{basis_amount:{quantity:row.scaling_basis_quantity,unit_id:row.scaling_basis_unit_id}}:{})}:undefined;
- return {...source,schema_version:row.schema_version,id:row.id,revision:row.revision,status:row.status,title:row.title,...(row.summary?{summary:row.summary}:{}),categories:json(row.categories_json,[]),tags:json(row.tags_json,[]),...(row.station?{station:row.station}:{}),...(row.auto_yield?{auto_yield:true}:{}),yield:{...(source.yield??{}),amount:{quantity:row.yield_quantity,unit_id:row.yield_unit_id},...(row.yield_servings!=null?{servings:row.yield_servings}:{}),...(row.yield_basis?{basis:row.yield_basis}:{})},...(scaling?{scaling}:{}),components,steps,notes:json(row.notes_json,[]),...(equipment_ids.length?{equipment_ids}:{})};
+ return {...source,schema_version:row.schema_version,id:row.id,title:row.title,...(row.summary?{summary:row.summary}:{}),categories:json(row.categories_json,[]),tags:json(row.tags_json,[]),...(row.station?{station:row.station}:{}),...(row.auto_yield?{auto_yield:true}:{}),yield:{...(source.yield??{}),amount:{quantity:row.yield_quantity,unit_id:row.yield_unit_id},...(row.yield_servings!=null?{servings:row.yield_servings}:{}),...(row.yield_basis?{basis:row.yield_basis}:{})},...(scaling?{scaling}:{}),components,steps,notes:json(row.notes_json,[]),...(equipment_ids.length?{equipment_ids}:{})};
});
return { generated_at:new Date().toISOString(),units,ingredients,equipment,prepActions,purchaseItems,sourceMappings,recipes };
}
diff --git a/scripts/site-project.mjs b/scripts/site-project.mjs
deleted file mode 100644
index 61e28eb..0000000
--- a/scripts/site-project.mjs
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env node
-import fs from "node:fs";
-import path from "node:path";
-import { DatabaseSync } from "node:sqlite";
-import { writeSiteProjection } from "./lib/site-projection.mjs";
-const databasePath=path.resolve(process.cwd(),"var","recipe-book.sqlite");
-if(!fs.existsSync(databasePath)) throw new Error(`Database does not exist: ${databasePath}`);
-const database=new DatabaseSync(databasePath,{readOnly:true});
-try { console.log(`Projected site data to ${writeSiteProjection(database)}`); } finally { database.close(); }
diff --git a/src/application/middleware.ts b/src/application/middleware.ts
new file mode 100644
index 0000000..46106d4
--- /dev/null
+++ b/src/application/middleware.ts
@@ -0,0 +1,19 @@
+import { defineMiddleware } from "astro:middleware";
+import { readOnlyMode } from "../lib/runtime";
+
+const safeMethods = new Set(["GET", "HEAD", "OPTIONS"]);
+
+export const onRequest = defineMiddleware(async ({ request, url, redirect }, next) => {
+ if (url.pathname === "/") return redirect("/app/", 302);
+ if (!readOnlyMode) return next();
+ if (!safeMethods.has(request.method)) {
+ return new Response("This Formulation instance is read-only.", { status: 405, headers: { Allow: "GET, HEAD, OPTIONS" } });
+ }
+ if (url.pathname.endsWith("/new/") || url.searchParams.has("edit")) {
+ const target = new URL(url);
+ target.searchParams.delete("edit");
+ if (target.pathname.endsWith("/new/")) target.pathname = "/app/";
+ return redirect(`${target.pathname}${target.search}${target.hash}`, 303);
+ }
+ return next();
+});
diff --git a/src/application/pages/api/app/entities/delete.ts b/src/application/pages/api/app/entities/delete.ts
index d43576f..f178154 100644
--- a/src/application/pages/api/app/entities/delete.ts
+++ b/src/application/pages/api/app/entities/delete.ts
@@ -21,7 +21,7 @@ export const POST:APIRoute=async({request})=>{
}
database.exec("BEGIN IMMEDIATE");
try {
- if(type==="recipe")database.prepare(`UPDATE recipes SET deleted_at=CURRENT_TIMESTAMP,status='archived' WHERE id IN (${placeholders})`).run(...ids);
+ if(type==="recipe")database.prepare(`UPDATE recipes SET deleted_at=CURRENT_TIMESTAMP WHERE id IN (${placeholders})`).run(...ids);
if(type==="ingredient")database.prepare(`UPDATE ingredients SET deleted_at=CURRENT_TIMESTAMP,status='archived' WHERE id IN (${placeholders})`).run(...ids);
if(type==="book")database.prepare(`UPDATE collections SET deleted_at=CURRENT_TIMESTAMP WHERE id IN (${placeholders})`).run(...ids);
if(type==="purchase")database.prepare(`DELETE FROM purchase_items WHERE id IN (${placeholders})`).run(...ids);
diff --git a/src/application/pages/app/archive.astro b/src/application/pages/app/archive.astro
index eebe4c8..c35c20c 100644
--- a/src/application/pages/app/archive.astro
+++ b/src/application/pages/app/archive.astro
@@ -3,7 +3,7 @@ export const prerender=false;
import BaseLayout from "../../../layouts/BaseLayout.astro";
import {openDatabase,refreshSiteProjection} from "../../../lib/database";
const database=openDatabase({readOnly:false});if(!database)return Astro.redirect("/app/",303);
-if(Astro.request.method==="POST"){const form=await Astro.request.formData(),type=String(form.get("type")),id=String(form.get("id"));const tables:{[key:string]:string}={recipe:"recipes",ingredient:"ingredients",book:"collections"};if(tables[type])database.prepare(`UPDATE ${tables[type]} SET deleted_at=NULL${type!=="book"?",status='active'":""} WHERE id=?`).run(id);refreshSiteProjection(database);database.close();return Astro.redirect("/app/archive/",303);}
+if(Astro.request.method==="POST"){const form=await Astro.request.formData(),type=String(form.get("type")),id=String(form.get("id"));const tables:{[key:string]:string}={recipe:"recipes",ingredient:"ingredients",book:"collections"};if(tables[type])database.prepare(`UPDATE ${tables[type]} SET deleted_at=NULL${type==="ingredient"?",status='active'":""} WHERE id=?`).run(id);refreshSiteProjection(database);database.close();return Astro.redirect("/app/archive/",303);}
const items=[...(database.prepare("SELECT id,title name,deleted_at FROM recipes WHERE deleted_at IS NOT NULL").all() as any[]).map(x=>({...x,type:"recipe"})),...(database.prepare("SELECT id,name,deleted_at FROM ingredients WHERE deleted_at IS NOT NULL").all() as any[]).map(x=>({...x,type:"ingredient"})),...(database.prepare("SELECT id,name,deleted_at FROM collections WHERE deleted_at IS NOT NULL").all() as any[]).map(x=>({...x,type:"book"}))].sort((a,b)=>a.name.localeCompare(b.name));database.close();
---
{items.length?items.map(item=>):Nothing has been archived.
}
diff --git a/src/application/pages/app/index.astro b/src/application/pages/app/index.astro
index 49c72a8..c19ce3b 100644
--- a/src/application/pages/app/index.astro
+++ b/src/application/pages/app/index.astro
@@ -3,10 +3,11 @@ export const prerender = false;
import BaseLayout from "../../../layouts/BaseLayout.astro";
import EntityDirectory from "../../../components/EntityDirectory";
import { openDatabase } from "../../../lib/database";
+import { readOnlyMode } from "../../../lib/runtime";
const database = openDatabase();
if (!database) return new Response("Database unavailable", { status:503 });
-const recipes=database.prepare(`SELECT r.id,r.title,r.status,r.revision,r.yield_quantity,r.yield_unit_id,
+const recipes=database.prepare(`SELECT r.id,r.title,r.yield_quantity,r.yield_unit_id,
(SELECT count(*) FROM recipe_items ri WHERE ri.recipe_id=r.id) item_count,
(SELECT count(*) FROM recipe_steps rs WHERE rs.recipe_id=r.id AND rs.instruction LIKE 'TODO:%') placeholder_count
FROM recipes r WHERE r.deleted_at IS NULL ORDER BY r.title`).all() as any[];
@@ -69,24 +70,24 @@ const purchaseRows=purchases.map(item=>({id:item.id,name:item.name,href:`/app/in
- }
{tabs.map((tab)=>{tab.icon} {tab.label} {tab.count} )}
{type==="ingredient"&&}
{type==="recipe"&&}
- Archive
+ {!readOnlyMode&&Archive }
{query?{searchResults.length} {searchResults.length===1?"result":"results"} for “{query}”{filteringSearchTypes&&` · ${selectedSearchTypes.length} item ${selectedSearchTypes.length===1?"type":"types"}`}
{searchResults.length?:No items of the selected types match this search.
} :<>
- {type==="ingredient"&& }
- {type==="recipe"&& }
- {type==="book"&& }
- {type==="purchase"&& }
+ {type==="ingredient"&&}
+ {type==="recipe"&&}
+ {type==="book"&&}
+ {type==="purchase"&&}
>}
diff --git a/src/application/pages/app/ingredients/[id].astro b/src/application/pages/app/ingredients/[id].astro
index 4436d1c..125e7f1 100644
--- a/src/application/pages/app/ingredients/[id].astro
+++ b/src/application/pages/app/ingredients/[id].astro
@@ -2,12 +2,13 @@
export const prerender = false;
import BaseLayout from "../../../../layouts/BaseLayout.astro";
import { openDatabase, refreshSiteProjection } from "../../../../lib/database";
+import { readOnlyMode } from "../../../../lib/runtime";
import { bestUsdaPortions, fetchUsdaFood, usdaNutrition } from "../../../../lib/usda";
import { number } from "../../../../lib/format";
import PurchaseItemForm from "../../../../components/PurchaseItemForm.astro";
import DetailUtility from "../../../../components/DetailUtility.astro";
const id = Astro.params.id!;
-const editing = Astro.url.searchParams.get("edit") === "1";
+const editing = !readOnlyMode && Astro.url.searchParams.get("edit") === "1";
const database = openDatabase({ readOnly: false });
if (!database) return Astro.redirect("/app/", 303);
let error: string | undefined;
@@ -106,7 +107,7 @@ const nutritionMappings = mappings.map((mapping) => {
return { ...mapping, source, sourceUrl, nutrients: Object.entries(nutrition).filter((entry): entry is [string, number] => typeof entry[1] === "number") as Array<[string, number]> };
});
const usdaMapping = nutritionMappings.find((mapping) => mapping.source.source_type === "usda_fdc");
-const usedIn=database.prepare("SELECT DISTINCT r.id,r.title,r.status FROM recipe_items i JOIN recipes r ON r.id=i.recipe_id WHERE i.ingredient_id=? ORDER BY r.title").all(id) as any[];
+const usedIn=database.prepare("SELECT DISTINCT r.id,r.title FROM recipe_items i JOIN recipes r ON r.id=i.recipe_id WHERE i.ingredient_id=? ORDER BY r.title").all(id) as any[];
const units=database.prepare("SELECT id,name,symbol,dimension FROM units ORDER BY dimension,name").all() as any[];
const mergeCandidates=editing?database.prepare("SELECT id,name FROM ingredients WHERE id<>? AND deleted_at IS NULL ORDER BY name").all(id) as any[]:[];
const unitById = new Map(units.map((unit) => [unit.id, unit]));
@@ -131,7 +132,7 @@ database.close();
-
+
{message&&{message}
}{error&&{error}
}
diff --git a/src/application/pages/app/recipe-books/[id].astro b/src/application/pages/app/recipe-books/[id].astro
index 55f5247..ab46e26 100644
--- a/src/application/pages/app/recipe-books/[id].astro
+++ b/src/application/pages/app/recipe-books/[id].astro
@@ -2,8 +2,9 @@
export const prerender=false;
import BaseLayout from "../../../../layouts/BaseLayout.astro";
import DetailUtility from "../../../../components/DetailUtility.astro";
+import {readOnlyMode} from "../../../../lib/runtime";
import {openDatabase,refreshSiteProjection} from "../../../../lib/database";
-const id=Astro.params.id!,editing=Astro.url.searchParams.get("edit")==="1";
+const id=Astro.params.id!,editing=!readOnlyMode&&Astro.url.searchParams.get("edit")==="1";
const database=openDatabase({readOnly:false});if(!database)return Astro.redirect("/app/?error=database-missing",303);
let error="";
if(Astro.request.method==="POST")try{const form=await Astro.request.formData(),intent=String(form.get("intent"));
@@ -12,7 +13,7 @@ if(Astro.request.method==="POST")try{const form=await Astro.request.formData(),i
refreshSiteProjection(database);database.close();return Astro.redirect(`/app/recipe-books/${id}/`,303);
}catch(cause){error=cause instanceof Error?cause.message:"Unable to save recipe book.";}
const book=database.prepare("SELECT * FROM collections WHERE id=? AND deleted_at IS NULL").get(id) as any;if(!book){database.close();return new Response("Recipe book not found",{status:404});}
-const recipes=database.prepare("SELECT r.id,r.title,r.status,cr.position,cr.recipe_id IS NOT NULL included FROM recipes r LEFT JOIN collection_recipes cr ON cr.recipe_id=r.id AND cr.collection_id=? WHERE r.deleted_at IS NULL ORDER BY coalesce(cr.position,999999),r.title").all(id) as any[];
+const recipes=database.prepare("SELECT r.id,r.title,cr.position,cr.recipe_id IS NOT NULL included FROM recipes r LEFT JOIN collection_recipes cr ON cr.recipe_id=r.id AND cr.collection_id=? WHERE r.deleted_at IS NULL ORDER BY coalesce(cr.position,999999),r.title").all(id) as any[];
database.close();
---
- {error&&{error}
}{editing&&}
+ {error&&{error}
}{editing&&}
diff --git a/src/application/pages/app/recipes/[id].astro b/src/application/pages/app/recipes/[id].astro
index a03391d..82fdab0 100644
--- a/src/application/pages/app/recipes/[id].astro
+++ b/src/application/pages/app/recipes/[id].astro
@@ -10,9 +10,10 @@ import { calculateCost } from "../../../../lib/costing";
import type { Ingredient, PrepAction, PurchaseItem, Recipe, SourceMapping, Unit } from "../../../../lib/types";
import DetailUtility from "../../../../components/DetailUtility.astro";
import { convertWithIngredientMeasures } from "../../../../lib/measurement";
+import { readOnlyMode } from "../../../../lib/runtime";
const id = Astro.params.id!;
-const editing = Astro.url.searchParams.get("edit") === "1";
+const editing = !readOnlyMode && Astro.url.searchParams.get("edit") === "1";
const database = openDatabase({ readOnly: false });
if (!database) return Astro.redirect("/app/?error=database-missing", 303);
let error: string | undefined;
@@ -33,9 +34,9 @@ if (Astro.request.method === "POST") {
refreshSiteProjection(database);database.close();return Astro.redirect(`/app/recipes/${id}/?edit=1#additional`,303);
}
if (form.get("intent") === "duplicate") {
- const duplicateId = duplicateRecipe(database, id);
+ const redirectTo = `/app/recipes/${duplicateRecipe(database, id)}/?edit=1`;
database.close();
- return Astro.redirect(`/app/recipes/${duplicateId}/?edit=1`, 303);
+ return Astro.redirect(redirectTo, 303);
}
if(form.get("intent")==="auto_yield"){
const current=editableRecipe(database,id);if(!current)throw new Error("Recipe not found.");
@@ -43,7 +44,7 @@ if (Astro.request.method === "POST") {
const source=JSON.parse(autoRow.source_json??"{}");
if(autoRow.auto_yield){
const original=source.auto_yield_original;
- if(original?.quantity>0&&original?.unit_id)saveRecipeMetadata(database,id,current.revision,{status:current.status,title:current.title,summary:current.summary,categories_json:current.categories_json,tags_json:current.tags_json,yield_quantity:original.quantity,yield_unit_id:original.unit_id,yield_servings:current.yield_servings,yield_basis:original.basis??null});
+ if(original?.quantity>0&&original?.unit_id)saveRecipeMetadata(database,id,current.save_version,{title:current.title,summary:current.summary,categories_json:current.categories_json,tags_json:current.tags_json,yield_quantity:original.quantity,yield_unit_id:original.unit_id,yield_servings:current.yield_servings,yield_basis:original.basis??null});
delete source.auto_yield_original;database.prepare("UPDATE recipes SET auto_yield=0,source_json=? WHERE id=?").run(JSON.stringify(source),id);refreshSiteProjection(database);database.close();return Astro.redirect(`/app/recipes/${id}/?edit=1&saved=1`,303);
}
const projectionNow=databaseProjection(database) as {recipes:Recipe[];ingredients:Ingredient[];units:Unit[];sourceMappings:SourceMapping[]};
@@ -55,7 +56,7 @@ if (Astro.request.method === "POST") {
if(conversionFailures.length)throw new Error(`Auto calculate total yield needs a weight equivalency for: ${conversionFailures.join(", ")}.`);
if(!(calculatedYieldWeightG>0))throw new Error("No convertible ingredient weights are available for automatic yield.");
source.auto_yield_original={quantity:current.yield_quantity,unit_id:current.yield_unit_id,basis:current.yield_basis};
- saveRecipeMetadata(database,id,current.revision,{status:current.status,title:current.title,summary:current.summary,categories_json:current.categories_json,tags_json:current.tags_json,yield_quantity:calculatedYieldWeightG,yield_unit_id:"gram",yield_servings:current.yield_servings,yield_basis:"theoretical"});
+ saveRecipeMetadata(database,id,current.save_version,{title:current.title,summary:current.summary,categories_json:current.categories_json,tags_json:current.tags_json,yield_quantity:calculatedYieldWeightG,yield_unit_id:"gram",yield_servings:current.yield_servings,yield_basis:"theoretical"});
database.prepare("UPDATE recipes SET auto_yield=1,source_json=? WHERE id=?").run(JSON.stringify(source),id);refreshSiteProjection(database);
database.close();return Astro.redirect(`/app/recipes/${id}/?edit=1&saved=1#nutrition`,303);
}
@@ -63,8 +64,8 @@ if (Astro.request.method === "POST") {
const current=editableRecipe(database,id);if(!current)throw new Error("Recipe not found.");
const yieldServings=Number(form.get("yield_servings"));
if(!Number.isFinite(yieldServings)||yieldServings<=0)throw new Error("Servings must be greater than zero.");
- const expectedRevision=Number(form.get("revision"));
- saveRecipeMetadata(database,id,expectedRevision,{status:current.status,title:current.title,summary:current.summary,categories_json:current.categories_json,tags_json:current.tags_json,yield_quantity:current.yield_quantity,yield_unit_id:current.yield_unit_id,yield_servings:yieldServings,yield_basis:current.yield_basis});
+ const expectedVersion=Number(form.get("save_version"));
+ saveRecipeMetadata(database,id,expectedVersion,{title:current.title,summary:current.summary,categories_json:current.categories_json,tags_json:current.tags_json,yield_quantity:current.yield_quantity,yield_unit_id:current.yield_unit_id,yield_servings:yieldServings,yield_basis:current.yield_basis});
database.close();return Astro.redirect(`/app/recipes/${id}/?edit=1#nutrition`,303);
}
if (form.get("intent") === "conversion") {
@@ -76,7 +77,6 @@ if (Astro.request.method === "POST") {
database.close(); return Astro.redirect(`/app/recipes/${id}/?edit=1#equivalencies`,303);
}
const title = String(form.get("title") ?? "").trim();
- const status = String(form.get("status") ?? "");
const yieldQuantity = Number(form.get("yield_quantity"));
const yieldUnitId = String(form.get("yield_unit_id") ?? "");
const servingsText = String(form.get("yield_servings") ?? "").trim();
@@ -85,14 +85,13 @@ if (Astro.request.method === "POST") {
const categories = String(form.get("categories") ?? "").split(",").map((value) => value.trim()).filter(Boolean);
const tags = String(form.get("tags") ?? "").split(",").map((value) => value.trim()).filter(Boolean);
if (!title) throw new Error("Title is required.");
- if (!["draft", "testing", "active", "retired", "archived"].includes(status)) throw new Error("Invalid status.");
if (!Number.isFinite(yieldQuantity) || yieldQuantity <= 0) throw new Error("Yield must be greater than zero.");
if (yieldServings != null && (!Number.isFinite(yieldServings) || yieldServings <= 0)) throw new Error("Servings must be greater than zero.");
if (!database.prepare("SELECT 1 FROM units WHERE id = ?").get(yieldUnitId)) throw new Error("Unknown yield unit.");
- const expectedRevision = Number(form.get("revision"));
- if (!Number.isInteger(expectedRevision) || expectedRevision < 1) throw new Error("Invalid recipe revision.");
- saveRecipeMetadata(database, id, expectedRevision, {
- status, title, summary: String(form.get("summary") ?? "").trim() || null,
+ const expectedVersion = Number(form.get("save_version"));
+ if (!Number.isInteger(expectedVersion) || expectedVersion < 1) throw new Error("Invalid save version.");
+ saveRecipeMetadata(database, id, expectedVersion, {
+ title, summary: String(form.get("summary") ?? "").trim() || null,
categories_json: JSON.stringify(categories), tags_json: JSON.stringify(tags),
yield_quantity: yieldQuantity, yield_unit_id: yieldUnitId,
yield_servings: yieldServings, yield_basis: yieldBasis,
@@ -107,11 +106,10 @@ if (Astro.request.method === "POST") {
const recipe = editableRecipe(database, id);
if (!recipe) { database.close(); return new Response("Recipe not found", { status: 404 }); }
const units = database.prepare("SELECT id, name, symbol, dimension FROM units ORDER BY dimension, name").all() as Array<{ id: string; name: string; symbol: string; dimension: string }>;
-const history = database.prepare("SELECT revision, saved_at, change_summary FROM recipe_revisions WHERE recipe_id = ? ORDER BY revision DESC LIMIT 10").all(id) as Array<{ revision: number; saved_at: string; change_summary: string }>;
const structure = recipeStructure(database, id)!;
const autoYield=Boolean((database.prepare("SELECT auto_yield FROM recipes WHERE id=?").get(id) as {auto_yield:number}).auto_yield);
const ingredientOptions = database.prepare("SELECT id, name FROM ingredients WHERE status = 'active' ORDER BY name").all() as Array<{ id: string; name: string }>;
-const recipeOptions = database.prepare("SELECT id, title AS name FROM recipes WHERE status NOT IN ('retired', 'archived') ORDER BY title").all() as Array<{ id: string; name: string }>;
+const recipeOptions = database.prepare("SELECT id, title AS name FROM recipes WHERE deleted_at IS NULL ORDER BY title").all() as Array<{ id: string; name: string }>;
const prepActionOptions = database.prepare("SELECT id, name FROM prep_actions ORDER BY name").all() as Array<{ id: string; name: string }>;
const recipeConversions=database.prepare("SELECT * FROM recipe_measure_conversions WHERE recipe_id=? ORDER BY id").all(id) as any[];
const additional=database.prepare("SELECT station,cover_media_url,notes_json,source_json FROM recipes WHERE id=?").get(id) as any;
@@ -134,7 +132,7 @@ const nutritionIngredients=domainRecipe.components.flatMap(component=>component.
const ingredient=ingredientMap.get(item.reference.ingredient_id)!;
const mapping=(ingredient.nutrition_mapping_ids??[]).map(mappingId=>nutritionMappingMap.get(mappingId)).find(mapping=>mapping?.mapping_type==="nutrition"&&mapping.status==="reviewed"&&Object.keys(mapping.nutrition_per_100g??{}).length>0);
let weightG:number|undefined;try{weightG=convertWithIngredientMeasures(item.amount,"gram",ingredient,unitMap).quantity;}catch{}
- return {id:item.id,name:ingredient.name,href:`/app/ingredients/${ingredient.id}/?edit=1#nutrition`,weightG,mapped:Boolean(mapping),source:mapping?.source.title,kind:"ingredient" as const};
+ return {id:item.id,name:ingredient.name,href:`/app/ingredients/${ingredient.id}/${readOnlyMode?"":"?edit=1"}#nutrition`,weightG,mapped:Boolean(mapping),source:mapping?.source.title,kind:"ingredient" as const};
}
const child=recipeMap.get(item.reference.recipe_id)!;
const childNutrition=calculateNutrition(child,{recipes:recipeMap,ingredients:ingredientMap,units:unitMap,mappings:nutritionMappingMap});
@@ -146,27 +144,27 @@ const categories = JSON.parse(recipe.categories_json).join(", ");
const tags = JSON.parse(recipe.tags_json).join(", ");
const saved = Astro.url.searchParams.get("saved") === "1";
---
-
+
-
+
{editing?<>☷ Prep Method $ Cost ⚖ UoM Equivalency ♡ Nutrition >:<>☷ Prep Method $ Cost ⚖ UoM Equivalency ♡ Nutrition >}
{editing?<>
UoM Equivalency Define how this finished recipe converts between weight, volume, and portions.
{recipeConversions.map(x=>{x.from_quantity} {x.from_unit_id} = {x.to_quantity} {x.to_unit_id} {x.notes}
)}
-
+
- Revision history · {history.length} {history.length?{history.map(entry=>Revision {entry.revision} {entry.saved_at} {entry.change_summary} )} :No application edits yet.
} >:<>
Prep Method {domainRecipe.steps.length} {domainRecipe.steps.map(step=>{step.order}. {step.instruction}{media.filter(entry=>entry.step_id===step.id).map(entry=>{entry.media_type==="image"? : }{entry.caption&&{entry.caption} } )} )} UoM Equivalency {recipeConversions.length?recipeConversions.map(x=>{x.from_quantity} {x.from_unit_id} = {x.to_quantity} {x.to_unit_id} {x.notes}
):No recipe-level equivalencies have been defined.
}{additional.cover_media_url&& }Additional details {additional.station&&
Station {additional.station}
}{shelfLife&&
Shelf life {shelfLife.duration.quantity} {shelfLife.duration.unit_id}{shelfLife.storage_condition?` · ${shelfLife.storage_condition}`:""}
}{JSON.parse(additional.notes_json??"[]").length>0&&
{JSON.parse(additional.notes_json).map((note:string)=>{note} )} }
>}
+ >:<>
Prep Method {domainRecipe.steps.length} {domainRecipe.steps.map(step=>{step.order}. {step.instruction}{media.filter(entry=>entry.step_id===step.id).map(entry=>{entry.media_type==="image"? : }{entry.caption&&{entry.caption} } )} )} UoM Equivalency {recipeConversions.length?recipeConversions.map(x=>{x.from_quantity} {x.from_unit_id} = {x.to_quantity} {x.to_unit_id} {x.notes}
):No recipe-level equivalencies have been defined.
}{additional.cover_media_url&& }Additional details {additional.station&&
Station {additional.station}
}{shelfLife&&
Shelf life {shelfLife.duration.quantity} {shelfLife.duration.unit_id}{shelfLife.storage_condition?` · ${shelfLife.storage_condition}`:""}
}{JSON.parse(additional.notes_json??"[]").length>0&&
{JSON.parse(additional.notes_json).map((note:string)=>{note} )} }
>}
{!editing&&}
{editing&&