# Formulation Formulation is a culinary recipe-management application for building, scaling, costing, and analyzing professional recipes. It models ingredients and sub-recipes as reusable entities instead of embedding duplicated ingredient data in every recipe. 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 - Structured recipes with components, sub-recipes, ordered preparation steps, yields, tags, and shelf life - Recipe scaling using amounts, standard percentages, or baker's percentages - Weight, volume, count, density, and ingredient-specific unit conversions - Preparation yields and loss or gain factors - Recursive nutrition and recipe costing - USDA FoodData Central mappings with source provenance - Ingredient aliases, purchasing packages, suppliers, and price history - Nutrition labels and missing-data indicators The [culinary data model](docs/culinary-data-model.md) documents entity boundaries, measurement semantics, provenance, and portability conventions. ## Requirements - Node.js 22.12 or newer - npm 9.6.5 or newer - Python 3 for schema and content validation utilities Install dependencies: ```bash npm ci python3 -m pip install --user -r requirements-dev.txt ``` ## Database & Backups SQLite is the canonical writable store. The database is located at `var/recipe-book.sqlite` and is intentionally excluded from Git. All normal recipe, ingredient, nutrition-mapping, and purchasing changes must be written to SQLite through the application or its validated database functions. This rule also applies to automated and AI-assisted edits. Do not edit `culinary/*.yaml` as a way to update a running application, and do not use unrestricted SQL when `saveRecipeStructure()` or another domain save function is available. ### Backup and Restore To create a full, verifiable JSON backup of the active database: ```bash npm run db:backup -- [path/to/backup.json] ``` To validate a backup bundle without modifying the database: ```bash npm run db:validate -- path/to/backup.json ``` To restore a backup into SQLite (transactional replace mode): ```bash npm run db:restore -- path/to/backup.json ``` Backups can also be downloaded and restored interactively through the web UI at `/app/settings/`. Generated projections and future YAML/JSON exports flow outward from SQLite. They are suitable for presentation, backup, interchange, and Git review, but must not be edited independently and treated as authoritative. See [Local application](docs/local-application.md) for more detail. For moving development to another machine, see [Agent handoff](docs/agent-handoff.md). ## Development Run the editor: ```bash npm run dev:app ``` Ingredient bulk entry uses the local Ollama service through `http://10.0.10.211:11434/api/chat` and the purpose-built `qwen3:4b-instruct` parsing prompt. Override these defaults with `FORMULATION_OLLAMA_URL` and `FORMULATION_INGREDIENT_PARSER_MODEL`. The parser endpoint is disabled whenever `FORMULATION_READ_ONLY=true`. Open . To stop any process listening on the application port and start a fresh Astro development server: ```bash npm run restart:app ``` Run the same application in read-only mode: ```bash npm run dev:readonly ``` Open . The database is opened read-only, modifying HTTP requests are rejected, and editing controls and routes are unavailable. ## Validation and builds Run type checks, unit tests, and the production build: ```bash npm run check npm test npm run build ``` 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 Validate portable culinary entities, schemas, and cross-references: ```bash scripts/validate-content ``` Search USDA FoodData Central and import a nutrition mapping: ```bash USDA_FDC_API_KEY=... scripts/usda-fdc search "all-purpose flour" USDA_FDC_API_KEY=... scripts/usda-fdc import flour_all_purpose 790018 ``` Use `--reviewed` only after confirming that the selected record describes the canonical ingredient. Never commit the USDA API key. Purchasing candidates can be proposed from the sibling `ledger` receipt archive and reviewed in the application: ```bash scripts/receipt-products propose scripts/receipt-products apply ~/Downloads/purchasing-decisions.json ``` The review interface is available at `/tools/purchasing-review/`. ## Knowledge export Generate the recipe corpus used by external knowledge systems: ```bash scripts/corpus-export ``` The Gitea Actions workflow in `.gitea/workflows/sync-knowledge.yml` can publish that corpus to an Open WebUI knowledge base. Configure these repository Actions variables: ```text OPEN_WEBUI_URL GOURMAND_KB_ID ``` Configure the API key as the `KNOWLEDGE_SYNC_OPEN_WEBUI_API_KEY` Actions secret. Generated exports are not committed.