174 lines
5.0 KiB
Markdown
174 lines
5.0 KiB
Markdown
# 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 <http://localhost:4322/app/>.
|
|
|
|
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 <http://localhost:4399/app/>. 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.
|