KitchenFlow Technical Specification
KitchenFlow - Recipe Management Application Specification
Version: 1.0.0-draft
Date: 2026-07-25
License: MIT
Package: tech.livingonlinux.kitchenflow
Target Platform: Linux (GNOME 45+, libadwaita 1.4+)
Language: Python 3.11+
Build System: Flatpak Builder + Meson
Executive Summary
KitchenFlow is a Linux-first, open-source recipe management application that uses a visual node-based graph interface to represent cooking workflows. Inspired by ComfyUI’s visual clarity and n8n’s workflow logic, it transforms recipes into executable, timed sequences that guide users through cooking with professional-grade repeatability.
Core Value Proposition:
- Visual node graph shows when and how to cook, not just what
- Intelligent timing synchronization (oven preheats while you prep)
- Equipment-aware recipe adaptation with fallback warnings
- Convergent design: works on phone, tablet, desktop
- Extensible architecture for future restaurant/KDS features
Design Philosophy
GNOME 50 / libadwaita Conventions
- AdwApplication as base application class
- AdwMainWindow with AdwNavigationPage for navigation
- AdwTabView for multi-recipe coordination
- AdwPreferencesWindow for settings/equipment configuration
- AdwStatusPage for empty states and onboarding
- AdwBanner for non-blocking alerts (equipment warnings)
- AdwToast for timer notifications
- System theme integration (light/dark mode)
- HIG-compliant spacing, margins, and typography
Convergent Design Principles
- Desktop: Full node editor, multi-recipe management
- Tablet: Touch-optimized execution mode, large timers
- Mobile: Simplified step-by-step view, voice-ready UI
- All form factors share the same codebase via responsive AdwBreakpoint
YAGNI & Modularity
- Core graph layer is testable and independent of UI
- Features added only when validated by user need
- Extension points defined but not implemented until required
- Each module has clear boundaries and minimal coupling
Technical Architecture
Technology Stack
| Component | Technology | Rationale |
|---|---|---|
| UI Framework | GTK 4.14+ / libadwaita 1.5+ | Native GNOME integration, HIG compliance |
| Language | Python 3.11+ | Rapid development, GTK4 Python bindings mature |
| Node Graph | gtk4-node-editor or libadwaita-graph | Reuse existing, well-maintained components |
| Data Persistence | JSON (recipes), GSettings (user prefs) | Human-readable, Flatpak-portable |
| Timers | asyncio event loop | Non-blocking, handles concurrent timers cleanly |
| Notifications | libportal (Flatpak portals) | Background timer alerts via system notifications |
| Testing | pytest + pytest-gtk | Test-driven development, UI automation ready |
| Build | Flatpak Builder + Meson | Flathub distribution standard |
Directory Structure
kitchenflow/
├── meson.build # Build configuration
├── data/
│ ├── tech.livingonlinux.kitchenflow.desktop
│ ├── tech.livingonlinux.kitchenflow.metainfo.xml
│ ├── icons/
│ │ └── hicolor/
│ │ └── scalable/
│ │ └── apps/
│ │ └── tech.livingonlinux.kitchenflow.svg
│ └── recipes/ # Sample recipes (MVP)
│ ├── basic-pasta.json
│ └── roast-chicken.json
├── src/
│ ├── __init__.py
│ ├── main.py # Application entry point
│ ├── application.py # AdwApplication subclass
│ ├── graph/ # Core graph layer (TESTABLE)
│ │ ├── __init__.py
│ │ ├── node.py # Node base class
│ │ ├── edge.py # Edge/connection class
│ │ ├── graph.py # DAG management
│ │ ├── node_types/ # Specific node implementations
│ │ │ ├── __init__.py
│ │ │ ├── ingredient.py
│ │ │ ├── prep.py
│ │ │ ├── cook.py
│ │ │ ├── wait.py
│ │ │ └── conditional.py
│ │ └── scheduler.py # Timing calculation engine
│ ├── ui/ # UI layer (depends on graph)
│ │ ├── __init__.py
│ │ ├── window.py # AdwMainWindow
│ │ ├── graph_view.py # Node graph visualization
│ │ ├── execution_view.py # Active cooking mode
│ │ ├── recipe_editor.py # Recipe construction (MVP2)
│ │ └── preferences.py # Equipment/settings
│ ├── models/ # Data models
│ │ ├── __init__.py
│ │ ├── recipe.py # Recipe dataclass
│ │ ├── equipment.py # User equipment config
│ │ └── ingredient.py # Ingredient inventory
│ ├── services/ # Business logic
│ │ ├── __init__.py
│ │ ├── timer_service.py # Timer management
│ │ ├── notification_service.py # Background alerts
│ │ └── import_export.py # JSON serialization
│ └── utils/
│ ├── __init__.py
│ └── formatting.py # Text-based recipe generation
├── tests/
│ ├── __init__.py
│ ├── conftest.py # pytest fixtures
│ ├── test_graph/
│ │ ├── test_node.py
│ │ ├── test_edge.py
│ │ ├── test_graph.py
│ │ └── test_scheduler.py
│ ├── test_models/
│ │ ├── test_recipe.py
│ │ └── test_equipment.py
│ └── test_services/
│ ├── test_timer_service.py
│ └── test_import_export.py
├── flatpak/
│ └── tech.livingonlinux.kitchenflow.json # Flatpak manifest
└── resources/
└── style.css # Custom theming (warm kitchen aesthetic)
Data Model
Recipe (DAG Structure)
@dataclass
class Recipe:
id: str # UUID or slug
name: str
description: str
author: str
created: datetime
modified: datetime
servings: int
prep_time: int # minutes (calculated)
cook_time: int # minutes (calculated)
total_time: int # minutes (calculated)
nodes: dict[str, Node] # node_id -> Node mapping
edges: list[Edge] # connections between nodes
equipment_required: set[str] # equipment IDs
ingredients: list[Ingredient]
tags: list[str]
difficulty: str # 'beginner', 'intermediate', 'advanced'
Node Types
class NodeType(Enum):
INGREDIENT = "ingredient" # Base ingredient (e.g., "onion")
PREP = "prep" # Preparation (e.g., "chop onion")
COOK = "cook" # Cooking action (e.g., "sauté")
WAIT = "wait" # Passive time (e.g., "rest 10 min")
CONDITIONAL = "conditional" # Branching logic (e.g., "if temp > 165°F")
EQUIPMENT = "equipment" # Equipment setup (e.g., "preheat oven")
GROUP = "group" # Collapsible section
Node Base Class
@dataclass
class Node:
id: str
type: NodeType
label: str
description: str
duration: int # minutes (0 for instant)
inputs: list[str] # upstream node IDs
outputs: list[str] # downstream node IDs
equipment_id: Optional[str] # required equipment
overrides: dict # user customization (e.g., skip_prep=true)
metadata: dict # type-specific data
Edge (Dependency)
@dataclass
class Edge:
id: str
source_node: str
target_node: str
source_port: Optional[str] # output port (for data flow)
target_port: Optional[str] # input port
label: Optional[str] # edge description (e.g., "provides")
Equipment Configuration
@dataclass
class Equipment:
id: str
name: str
type: str # 'oven', 'stovetop', 'air_fryer', etc.
preheat_time: int # minutes (configurable)
max_capacity: Optional[str] # e.g., "5L", "large pan"
temperature_range: tuple[int, int] # (min, max) in °F or °C
is_available: bool # user can disable unavailable equipment
Node Input/Output Design
Tradeoff Analysis: ComfyUI vs n8n
| Aspect | ComfyUI Style | n8n Style | KitchenFlow Decision |
|---|---|---|---|
| Data Flow | Explicit ports, type-checked | Implicit, dependency-based | Hybrid: Visual ports but semantic validation |
| Complexity | High learning curve | Lower barrier | Simplified ports: Only show relevant connections |
| Flexibility | Unlimited connections | Linear workflows | DAG with constraints: No cycles, max 3 inputs/outputs |
| Cooking Context | Abstract data | Task orchestration | Task orchestration with ingredient tracking |
Implementation Decision
KitchenFlow uses semantic dependency tracking rather than strict port matching:
- Ingredients flow implicitly: If Node A produces “chopped onion” and Node B requires “chopped onion”, the connection is automatic (user can override)
- Equipment is explicit: Nodes requiring specific equipment show equipment ports
- Timing is automatic: Scheduler calculates parallel vs sequential based on dependencies
- Validation happens at runtime: Missing ingredients/equipment trigger warnings before execution
Rationale: Cooking is less about data transformation (ComfyUI) and more about resource coordination (n8n). The visual graph should communicate dependencies and timing, not data schemas.
User Interface Specifications
View 1: Recipe Browser (Home)
┌─────────────────────────────────────────────────────────────┐
│ KitchenFlow [+ New Recipe] │
├─────────────────────────────────────────────────────────────┤
│ [Search recipes...] │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Roast │ │ Pasta │ │ Custom │ │
│ │ Chicken │ │ Carbonara │ │ Recipe 1 │ │
│ │ 45 min │ │ 30 min │ │ -- │ │
│ │ [▶ Cook] │ │ [▶ Cook] │ │ [✏ Edit] │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Stir Fry │ │ Bread │ │
│ │ 25 min │ │ 180 min │ │
│ │ [▶ Cook] │ │ [▶ Cook] │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
Components:
AdwHeaderBarwith searchAdwClampfor content centeringGtkFlowBoxfor recipe cards- Recipe cards show: name, time, difficulty badge, action button
View 2: Graph View (Recipe Detail)
┌─────────────────────────────────────────────────────────────┐
│ ← Roast Chicken [⚙️] [▶ Start Cooking] │
├─────────────────────────────────────────────────────────────┤
│ [Graph] [Text] [Ingredients] │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Oven │────▶│ Roast │────▶│ Rest │ │
│ │Preheat │ 40m │ Chicken │ 1h │ 10 min │ │
│ │ 15 min │ │ │ │ │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ ▲ │
│ │ │ │
│ ┌────┴────┐ ┌──────┴──────┐ │
│ │ Onion │ │ Internal │ │
│ │ Chop │ │ Temp Check │ │
│ │ 5 min │ │ (165°F) │ │
│ └─────────┘ └─────────────┘ │
│ │
│ Currently Underway: [None] │
│ Up Next: Preheat oven (ready in 15 min) │
└─────────────────────────────────────────────────────────────┘
Components:
gtk4-node-editoror customGtkDrawingAreafor graph- Tab switcher for Graph/Text/Ingredients views
- Status bar showing active/next steps
- Warm color scheme (see Style section)
View 3: Execution Mode (Active Cooking)
┌─────────────────────────────────────────────────────────────┐
│ ← Roast Chicken - Cooking [⏸Pause]│
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────┐ │
│ │ │ │
│ │ ROAST CHICKEN │ │
│ │ │ │
│ │ 43:27 remaining │ │
│ │ │ │
│ │ ┌───────────────┐ │ │
│ │ │ 02:15 │ │ │
│ │ │ REMAINING │ │ │
│ │ │ │ │ │
│ │ │ ROASTING │ │ │
│ │ │ @ 425°F │ │ │
│ │ └───────────────┘ │ │
│ │ │ │
│ │ [✅ Mark Complete] │ │
│ │ │ │
│ └─────────────────────────┘ │
│ │
│ Next: Rest chicken 10 min → Check internal temp │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Timeline │ │
│ │ [Preheat]══[ROASTING]══[Rest]══[Temp Check] │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Components:
- Full-screen
AdwOverlaySplitView(collapsible details) - Large timer display (AdwStatusPage or custom
GtkLabel) - Touch-friendly action buttons (min 48×48 dp)
- Progress timeline using
GtkProgressBarwith segments - System notifications for timer completion
View 4: Preferences / Equipment Setup
┌─────────────────────────────────────────────────────────────┐
│ ← Settings │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Equipment │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ Oven [Edit] [Preheat: 15 min] │ │
│ │ Stovetop [Edit] [Preheat: 3 min] │ │
│ │ Air Fryer [Edit] [Preheat: 5 min] │ │
│ │ [+ Add Equipment] │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Ingredients Inventory │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ Onions (pre-chopped: ❌) │ │
│ │ Garlic (minced: ❌) │ │
│ │ [+ Manage Inventory] │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Notifications │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ [✓] Background timer alerts │ │
│ │ [✓] Sound on completion │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Style Guide (Warm Kitchen Aesthetic)
Color Palette
/* resources/style.css */
/* Warm neutrals */
@define-color kitchen-bg #fdf6e3; /* Cream background */
@define-color kitchen-surface #f5e6d3; /* Warm surface */
@define-color kitchen-border #d4c4b0; /* Subtle borders */
/* Action colors */
@define-color prep-color #87ceeb; /* Sky blue for prep */
@define-color cook-color #ff8c42; /* Warm orange for cooking */
@define-color wait-color #90ee90; /* Soft green for resting */
@define-color equipment-color #dda0dd; /* Purple for equipment */
@define-color ingredient-color #ffb6c1; /* Pink for ingredients */
/* Alerts */
@define-color warning-color #ffd700; /* Gold for warnings */
@define-color error-color #ff6b6b; /* Red for errors */
/* libadwaita integration */
@define-color theme_bg_color @kitchen-bg;
@define-color theme_fg_color #2d2d2d;
@define-color card_bg_color @kitchen-surface;
Node Styling
.node-ingredient {
background: @ingredient-color;
border: 2px solid darken(@ingredient-color, 20%);
border-radius: 12px;
}
.node-prep {
background: @prep-color;
border: 2px solid darken(@prep-color, 20%);
border-radius: 12px;
}
.node-cook {
background: @cook-color;
border: 2px solid darken(@cook-color, 20%);
border-radius: 12px;
font-weight: bold;
}
.node-wait {
background: @wait-color;
border: 2px solid darken(@wait-color, 20%);
border-radius: 12px;
font-style: italic;
}
.node-active {
box-shadow: 0 0 0 4px alpha(@cook-color, 0.4);
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { box-shadow: 0 0 0 4px alpha(@cook-color, 0.4); }
50% { box-shadow: 0 0 0 8px alpha(@cook-color, 0.2); }
}
Milestone Breakdown
MVP Phase 1: Core Graph Layer (Weeks 1-3)
Goal: Testable DAG infrastructure with 3 node types
Deliverables:
-
graph/node.py- Base Node class with serialization -
graph/edge.py- Edge class with validation -
graph/graph.py- DAG management (add/remove nodes, cycle detection) -
graph/node_types/prep.py- PrepNode implementation -
graph/node_types/cook.py- CookNode implementation -
graph/node_types/wait.py- WaitNode implementation -
tests/test_graph/- Full test suite (target: 90% coverage) - JSON schema for recipe serialization
Validation Criteria:
- Can create, load, and save a recipe graph
- Cycle detection works correctly
- Topological sort produces valid execution order
- All tests pass
MVP Phase 2: Timer & Execution Engine (Weeks 4-5)
Goal: Runnable recipe with timers and notifications
Deliverables:
-
services/timer_service.py- Async timer manager -
services/notification_service.py- Flatpak portal notifications -
graph/scheduler.py- Timing calculation (parallel vs sequential) -
ui/execution_view.py- Active cooking UI - Background timer support (requires
systemd-timeror portal)
Validation Criteria:
- Timers fire correctly for concurrent steps
- System notifications work when app is minimized
- User can mark steps complete, triggering next steps
MVP Phase 3: Graph Visualization (Weeks 6-7)
Goal: View recipes as interactive node graphs
Deliverables:
-
ui/graph_view.py- Node graph rendering - Custom node styling (warm kitchen aesthetic)
- Zoom/pan controls
- Tab switcher (Graph/Text/Ingredients views)
- Text-based recipe generation from graph
Validation Criteria:
- Graph renders correctly for sample recipes
- Users can navigate and zoom
- Text view accurately reflects graph data
MVP Phase 4: Recipe Browser & Import/Export (Weeks 8-9)
Goal: Complete user workflow from selection to cooking
Deliverables:
-
ui/window.py- Main application window - Recipe browser (flow box with cards)
-
services/import_export.py- JSON serialization - Sample recipe library (5-10 recipes)
- Equipment configuration UI
Validation Criteria:
- Users can browse, select, and start recipes
- JSON import/export works round-trip
- Equipment warnings show for missing tools
MVP Release (Week 10)
Deliverables:
- Flatpak manifest (
tech.livingonlinux.kitchenflow.json) - AppData metadata for Flathub
- Icon set (scalable SVG)
- README.md with build instructions
- CHANGELOG.md
- Submit to Flathub
Testing Strategy
Test Pyramid
┌─────────────┐
│ E2E Tests │ (5-10 tests)
│ (UI + Graph) │
└───────────────┘
┌───────────────────┐
│ Integration │ (20-30 tests)
│ (Services + Graph) │
└─────────────────────┘
┌───────────────────────┐
│ Unit Tests │ (100+ tests)
│ (Nodes, Edges, Models) │
└─────────────────────────┘
Unit Test Examples
# tests/test_graph/test_node.py
def test_prep_node_creation():
node = PrepNode(
id="chop_onion",
label="Chop Onion",
duration=5,
ingredient="onion"
)
assert node.type == NodeType.PREP
assert node.duration == 5
assert node.is_complete() == False
def test_node_mark_complete():
node = WaitNode(id="rest", duration=10)
node.start()
assert node.elapsed == 0
node.mark_complete()
assert node.is_complete() == True
assert node.remaining == 0
def test_cook_node_temperature():
node = CookNode(
id="roast",
label="Roast Chicken",
duration=60,
temperature=425,
equipment_id="oven"
)
assert node.metadata["temperature"] == 425
Graph Validation Tests
# tests/test_graph/test_graph.py
def test_graph_no_cycles():
graph = RecipeGraph()
graph.add_node(NodeA)
graph.add_node(NodeB)
graph.add_edge(NodeA.id, NodeB.id)
# Attempt to create cycle
with pytest.raises(CycleError):
graph.add_edge(NodeB.id, NodeA.id)
def test_topological_sort():
graph = create_roast_chicken_graph()
order = graph.topological_sort()
assert order.index("preheat_oven") < order.index("roast")
assert order.index("chop_onion") < order.index("sauté")
def test_parallel_step_detection():
graph = create_roast_chicken_graph()
parallel = graph.get_parallel_steps()
assert "chop_onion" in parallel[0] # Can run with preheat
assert "roast" not in parallel[0] # Must wait for preheat
Integration Test Examples
# tests/test_services/test_timer_service.py
@pytest.mark.asyncio
async def test_concurrent_timers():
timer_service = TimerService()
completed = []
async def on_complete(step_id):
completed.append(step_id)
timer_service.register_callback(on_complete)
timer_service.start_step("preheat", duration=15)
timer_service.start_step("chop", duration=5)
await asyncio.sleep(6) # Wait for chop to complete
assert "chop" in completed
assert "preheat" not in completed
await asyncio.sleep(15) # Wait for preheat
assert "preheat" in completed
UI Automation Tests
# tests/test_ui/test_execution_view.py
def test_timer_display(gtk_app):
window = gtk_app.active_window
execution_view = window.execution_view
assert execution_view.timer_label.get_text() == "00:00"
execution_view.start_step("roast", duration=60)
assert execution_view.timer_label.get_text() == "59:59"
CI/CD Integration
# .github/workflows/test.yml (or Gitea Actions equivalent)
name: Test Suite
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install pytest pytest-asyncio pytest-gtk
pip install -r requirements.txt
- name: Run unit tests
run: pytest tests/test_graph tests/test_models -v
- name: Run integration tests
run: pytest tests/test_services -v
- name: Coverage report
run: pytest --cov=src --cov-report=xml
- name: Lint
run: |
pip install flake8 black isort
flake8 src
black --check src
isort --check src
Flatpak Packaging
Flatpak Manifest
// flatpak/tech.livingonlinux.kitchenflow.json
{
"app-id": "tech.livingonlinux.kitchenflow",
"runtime": "org.gnome.Platform",
"runtime-version": "45",
"sdk": "org.gnome.Sdk",
"default-branch": "main",
"command": "kitchenflow",
"finish-args": [
"--share=ipc",
"--socket=fallback-x11",
"--socket=wayland",
"--filesystem=home:ro",
"--filesystem=xdg-data/kitchenflow:create",
"--talk-name=org.freedesktop.Notifications",
"--device=dri"
],
"modules": [
{
"name": "kitchenflow",
"buildsystem": "meson",
"sources": [
{
"type": "git",
"url": "https://github.com/livingonlinux/kitchenflow.git",
"branch": "main"
}
],
"config-opts": [
"-Dprefix=/app",
"-Dbuildtype=release"
]
}
]
}
AppData Metadata
<!-- data/tech.livingonlinux.kitchenflow.metainfo.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>tech.livingonlinux.kitchenflow</id>
<metadata_license>FSFAP</metadata_license>
<project_license>MIT</project_license>
<name>KitchenFlow</name>
<summary>Visual recipe management with intelligent timing</summary>
<description>
<p>
KitchenFlow transforms recipes into visual, executable workflows.
See exactly when to start each step, what equipment you need,
and how to coordinate multiple dishes for perfect timing.
</p>
<p>Features:</p>
<ul>
<li>Visual node-based recipe editor</li>
<li>Intelligent timing synchronization</li>
<li>Equipment-aware recipe adaptation</li>
<li>Timer notifications in background</li>
<li>JSON import/export for sharing</li>
<li>Convergent design (phone, tablet, desktop)</li>
</ul>
</description>
<launchable type="desktop-id">tech.livingonlinux.kitchenflow.desktop</launchable>
<screenshots>
<screenshot type="default">
<image>https://raw.githubusercontent.com/livingonlinux/kitchenflow/main/screenshots/graph-view.png</image>
<caption>Visual recipe graph with timing</caption>
</screenshot>
</screenshots>
<url type="homepage">https://github.com/livingonlinux/kitchenflow</url>
<url type="bugtracker">https://github.com/livingonlinux/kitchenflow/issues</url>
<content_rating type="oars-1.1" />
<releases>
<release version="1.0.0" date="2026-01-15">
<description>
<p>Initial release</p>
</description>
</release>
</releases>
</component>
Desktop File
# data/tech.livingonlinux.kitchenflow.desktop
[Desktop Entry]
Name=KitchenFlow
Comment=Visual recipe management with intelligent timing
Exec=kitchenflow %U
Icon=tech.livingonlinux.kitchenflow
Terminal=false
Type=Application
Categories=GNOME;GTK;Utility;FoodDrink;
Keywords=recipe;cooking;timer;kitchen;
MimeType=application/x-kitchenflow-recipe;
Future Extensibility Points
Phase 2: Recipe Editor (Post-MVP)
- Full node graph editor (drag-drop, connect nodes)
- Template library with 50+ starter recipes
- AI-assisted recipe conversion (external tool, JSON import)
Phase 3: Smart Scheduling
- Automatic start-time calculation
- Multi-recipe coordination (dinner party mode)
- Equipment conflict resolution
Phase 4: Professional Features
- Portion scaling with ingredient adjustment
- Restaurant mode (multi-station KDS)
- Inventory integration
- API for third-party extensions
Phase 5: Mobile/Tablet Optimization
- Dedicated mobile execution view
- Voice commands (hands-free)
- Smart home integration (Nest, smart plugs)
Design Concerns & Mitigations
Concern 1: Node Graph Complexity
Issue: ComfyUI-style graphs can overwhelm casual users.
Mitigation:
- Default to “Guided Mode” (text-based step list)
- Graph view is optional, not required
- Progressive disclosure: simple recipes show minimal nodes
- Tooltips explain each node type on first use
Concern 2: Timing Accuracy
Issue: Real cooking times vary (stove power, oven calibration).
Mitigation:
- All timers are suggestions, not强制执行
- User can adjust durations per recipe
- “Snooze” feature for variable steps (“cook until golden”)
- Learn from user adjustments (future: ML-based timing)
Concern 3: Equipment Availability
Issue: Users may not have recommended equipment.
Mitigation:
- Equipment setup wizard on first run
- Clear warnings when recipe requires unavailable equipment
- Manual override with “this may affect results” warning
- Suggest alternative steps based on available equipment
Concern 4: Recipe Copyright
Issue: Importing recipes from external sources may violate copyright.
Mitigation:
- App does not scrape websites (user-provided JSON only)
- Sample recipes are original or CC-licensed
- Document user responsibility for imported content
- Future: Recipe registry with contributor agreements
Build & Development Instructions
Prerequisites
# Ubuntu/Debian
sudo apt install python3 python3-pip python3-venv \
libadwaita-1-0 libadwaita-1-dev \
gir1.2-adw-1 gir1.2-gtk-4.0 \
meson ninja-build flatpak flatpak-builder
# Fedora
sudo dnf install python3 python3-pip python3-virtualenv \
libadwaita libadwaita-devel \
gobject-introspection-devel gtk4-devel \
meson ninja-build flatpak flatpak-builder
Local Development Setup
# Clone repository
git clone https://github.com/livingonlinux/kitchenflow.git
cd kitchenflow
# Create virtual environment
python3 -m venv venv
source venv/bin/activate
# Install Python dependencies
pip install -r requirements.txt
# Run tests
pytest tests/
# Run application
python -m src.main
Flatpak Build
# Install Flatpak runtime
flatpak install flathub org.gnome.Platform//45
flatpak install flathub org.gnome.Sdk//45
# Build
flatpak-builder --force-clean build-dir flatpak/tech.livingonlinux.kitchenflow.json
# Run locally
flatpak run tech.livingonlinux.kitchenflow
Testing
# All tests
pytest tests/ -v
# Coverage report
pytest tests/ --cov=src --cov-report=html
# Specific test file
pytest tests/test_graph/test_graph.py -v
# Watch mode (auto-runs on file change)
pytest tests/ --looponfail
License
MIT License
Copyright (c) 2026 James (LivingOnLinux)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Appendix: Sample Recipe JSON
{
"id": "roast-chicken-basic",
"name": "Classic Roast Chicken",
"description": "Simple whole roasted chicken with vegetables",
"author": "LivingOnLinux",
"created": "2026-01-01T00:00:00Z",
"modified": "2026-01-01T00:00:00Z",
"servings": 4,
"prep_time": 15,
"cook_time": 75,
"total_time": 90,
"difficulty": "intermediate",
"tags": ["dinner", "protein", "one-pan"],
"ingredients": [
{"id": "chicken", "name": "Whole Chicken", "quantity": 1, "unit": "piece", "notes": "3-4 lbs"},
{"id": "onion", "name": "Onion", "quantity": 1, "unit": "piece", "state": "whole"},
{"id": "carrot", "name": "Carrot", "quantity": 2, "unit": "piece", "state": "whole"},
{"id": "olive_oil", "name": "Olive Oil", "quantity": 2, "unit": "tbsp"}
],
"equipment_required": ["oven", "roasting_pan"],
"nodes": {
"preheat_oven": {
"id": "preheat_oven",
"type": "equipment",
"label": "Preheat Oven",
"description": "Set oven to 425°F",
"duration": 15,
"inputs": [],
"outputs": ["roast_chicken"],
"equipment_id": "oven",
"metadata": {"temperature": 425, "unit": "F"}
},
"chop_onion": {
"id": "chop_onion",
"type": "prep",
"label": "Chop Onion",
"description": "Dice onion into 1/2-inch pieces",
"duration": 5,
"inputs": [],
"outputs": ["prep_vegetables"],
"equipment_id": null,
"metadata": {"ingredient": "onion", "cut": "dice"}
},
"roast_chicken": {
"id": "roast_chicken",
"type": "cook",
"label": "Roast Chicken",
"description": "Roast until internal temperature reaches 165°F",
"duration": 60,
"inputs": ["preheat_oven"],
"outputs": ["rest_chicken"],
"equipment_id": "oven",
"metadata": {"temperature": 425, "target_temp": 165, "unit": "F"}
},
"rest_chicken": {
"id": "rest_chicken",
"type": "wait",
"label": "Rest Chicken",
"description": "Let chicken rest before carving",
"duration": 10,
"inputs": ["roast_chicken"],
"outputs": [],
"equipment_id": null,
"metadata": {}
}
},
"edges": [
{"id": "e1", "source": "preheat_oven", "target": "roast_chicken"},
{"id": "e2", "source": "chop_onion", "target": "roast_chicken"},
{"id": "e3", "source": "roast_chicken", "target": "rest_chicken"}
]
}
Appendix: Text-Based Recipe Generation
# Generated from graph above:
# Classic Roast Chicken
# Serves 4 | Total Time: 90 minutes
## Ingredients
- 1 Whole Chicken (3-4 lbs)
- 1 Onion
- 2 Carrots
- 2 tbsp Olive Oil
## Instructions
1. **Preheat Oven** (15 minutes)
- Set oven to 425°F
2. **Chop Onion** (5 minutes)
- Dice onion into 1/2-inch pieces
- *Can be done while oven preheats*
3. **Roast Chicken** (60 minutes)
- Place chicken in roasting pan
- Cook at 425°F until internal temperature reaches 165°F
4. **Rest Chicken** (10 minutes)
- Let chicken rest before carving
## Equipment Needed
- Oven
- Roasting pan
## Timing Notes
- Start oven first (15 min preheat)
- Chop vegetables during preheat
- Total active time: 20 minutes
- Total passive time: 70 minutes
Revision History
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0.0-draft | 2026-01-15 | James | Initial specification |