chore: initialize recipe-manager project with agentic harness
- PROJECT.md: Product vision, success criteria, constraints - ARCHITECTURE.md: Tech stack, patterns, deployment strategy - ROADMAP.md: MVP → v1 → v2 milestone planning - AGENT_INSTRUCTIONS.md: Development workflow for autonomous agents - README.md: Project overview and quick start - TODO.md: Task tracking - .gitignore: Standard Node.js/Docker exclusions Project ready for first agent sprint (MVP development).
This commit is contained in:
commit
6552640cfa
|
|
@ -0,0 +1,56 @@
|
||||||
|
# Dependencies
|
||||||
|
node_modules/
|
||||||
|
.pnpm-store/
|
||||||
|
|
||||||
|
# Build outputs
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
.next/
|
||||||
|
out/
|
||||||
|
|
||||||
|
# Database & data
|
||||||
|
data/
|
||||||
|
*.db
|
||||||
|
*.db-shm
|
||||||
|
*.db-wal
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.production
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs/
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
# OS files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# Test coverage
|
||||||
|
coverage/
|
||||||
|
.nyc_output/
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
*.tmp
|
||||||
|
|
||||||
|
# Lock files (keep package-lock.json)
|
||||||
|
# pnpm-lock.yaml # Uncomment if using pnpm
|
||||||
|
|
||||||
|
# Backup files
|
||||||
|
*.bak
|
||||||
|
*~
|
||||||
|
|
@ -0,0 +1,333 @@
|
||||||
|
# Recipe Manager — Agent Instructions
|
||||||
|
|
||||||
|
**Purpose:** How agents should approach development on this project
|
||||||
|
**Last Updated:** 2026-03-23
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Core Principles
|
||||||
|
|
||||||
|
### 1. Orientation First
|
||||||
|
Every time you wake up (new session):
|
||||||
|
1. Read `PROJECT.md` — What are we building?
|
||||||
|
2. Read `ARCHITECTURE.md` — How are we building it?
|
||||||
|
3. Read `ROADMAP.md` — What's next?
|
||||||
|
4. Read `git log --oneline -10` — What happened recently?
|
||||||
|
5. Check `TODO.md` (if exists) — Any pending tasks?
|
||||||
|
|
||||||
|
**Never start coding without context.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Development Loop
|
||||||
|
|
||||||
|
### The Agent Workflow (Single Iteration)
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ 1. ORIENT Read context files, git log │
|
||||||
|
└────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌────────────┴────────────────────────────────────┐
|
||||||
|
│ 2. PLAN Pick ONE task from roadmap │
|
||||||
|
│ Break into <1hr subtasks if needed │
|
||||||
|
└────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌────────────┴────────────────────────────────────┐
|
||||||
|
│ 3. IMPLEMENT Write code + tests │
|
||||||
|
│ Follow architecture patterns │
|
||||||
|
└────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌────────────┴────────────────────────────────────┐
|
||||||
|
│ 4. VERIFY Run tests, lint, manual check │
|
||||||
|
│ Does it meet acceptance criteria? │
|
||||||
|
└────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌────────────┴────────────────────────────────────┐
|
||||||
|
│ 5. COMMIT Conventional commit message │
|
||||||
|
│ Update docs (README, ADR, etc.) │
|
||||||
|
└────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌────────────┴────────────────────────────────────┐
|
||||||
|
│ 6. REPORT Summarize what you did + what's │
|
||||||
|
│ next (or escalate if blocked) │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**One loop = one commit.** Don't try to do everything at once.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task Selection Rules
|
||||||
|
|
||||||
|
### What to Work On
|
||||||
|
|
||||||
|
1. **Check ROADMAP.md** for the current milestone
|
||||||
|
2. **Pick the next uncompleted feature** in that milestone
|
||||||
|
3. **If all features done,** move to testing/documentation
|
||||||
|
4. **If milestone complete,** report to Paul for approval before moving to next
|
||||||
|
|
||||||
|
### How to Break Down Tasks
|
||||||
|
|
||||||
|
**Good task (1-4 hours):**
|
||||||
|
- "Implement recipe list API endpoint with pagination"
|
||||||
|
- "Add tag filtering to search UI"
|
||||||
|
- "Write E2E test for cook mode"
|
||||||
|
|
||||||
|
**Bad task (too big):**
|
||||||
|
- "Build entire recipe import system"
|
||||||
|
- "Finish frontend"
|
||||||
|
|
||||||
|
**If task feels big (>4 hours),** break it into subtasks and commit each one.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Code Quality Standards
|
||||||
|
|
||||||
|
### TypeScript
|
||||||
|
- ✅ Strict mode enabled
|
||||||
|
- ✅ No `any` types (use `unknown` if needed)
|
||||||
|
- ✅ All public APIs have JSDoc comments
|
||||||
|
- ✅ Interfaces for all data models
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
- ✅ Unit test new business logic (services, utilities)
|
||||||
|
- ✅ Integration test API endpoints
|
||||||
|
- ✅ E2E test critical user flows (cook mode, search)
|
||||||
|
- ✅ Aim for >80% coverage on core logic
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
- ✅ Conventional Commits format: `type(scope): description`
|
||||||
|
- `feat:` new feature
|
||||||
|
- `fix:` bug fix
|
||||||
|
- `docs:` documentation only
|
||||||
|
- `test:` test additions/changes
|
||||||
|
- `refactor:` code restructure (no behavior change)
|
||||||
|
- `chore:` tooling, dependencies
|
||||||
|
- ✅ Descriptive messages (not "fix stuff" or "wip")
|
||||||
|
- ✅ Commit working code only (tests pass)
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- ✅ Update README when setup changes
|
||||||
|
- ✅ Add ADR (Architecture Decision Record) in `docs/` for significant choices
|
||||||
|
- Format: `ADR-001-why-sqlite.md`, `ADR-002-recipe-scraping-strategy.md`
|
||||||
|
- ✅ Update API docs when endpoints change
|
||||||
|
- ✅ Keep TODO.md current (add new tasks, remove completed)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### API Endpoint Template
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/routes/recipes.ts
|
||||||
|
import { Router } from 'express';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { RecipeService } from '../services/RecipeService';
|
||||||
|
|
||||||
|
const router = Router();
|
||||||
|
const recipeService = new RecipeService();
|
||||||
|
|
||||||
|
// Validation schema
|
||||||
|
const createRecipeSchema = z.object({
|
||||||
|
title: z.string().min(1),
|
||||||
|
ingredients: z.array(z.string()),
|
||||||
|
instructions: z.array(z.string()),
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/recipes', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const data = createRecipeSchema.parse(req.body);
|
||||||
|
const recipe = await recipeService.create(data);
|
||||||
|
res.json({ success: true, data: recipe });
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof z.ZodError) {
|
||||||
|
res.status(400).json({ success: false, error: error.errors });
|
||||||
|
} else {
|
||||||
|
res.status(500).json({ success: false, error: 'Internal error' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
|
```
|
||||||
|
|
||||||
|
### React Component Template
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/components/RecipeCard.tsx
|
||||||
|
import { Recipe } from '../types/recipe';
|
||||||
|
|
||||||
|
interface RecipeCardProps {
|
||||||
|
recipe: Recipe;
|
||||||
|
onEdit: (id: number) => void;
|
||||||
|
onDelete: (id: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RecipeCard({ recipe, onEdit, onDelete }: RecipeCardProps) {
|
||||||
|
return (
|
||||||
|
<div className="border rounded-lg p-4 shadow-sm">
|
||||||
|
<h3 className="text-lg font-bold">{recipe.title}</h3>
|
||||||
|
<p className="text-gray-600">{recipe.description}</p>
|
||||||
|
{/* ... */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database Query Template
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/repositories/RecipeRepository.ts
|
||||||
|
import Database from 'better-sqlite3';
|
||||||
|
import { Recipe } from '../types/recipe';
|
||||||
|
|
||||||
|
export class RecipeRepository {
|
||||||
|
constructor(private db: Database.Database) {}
|
||||||
|
|
||||||
|
findAll(): Recipe[] {
|
||||||
|
const stmt = this.db.prepare('SELECT * FROM recipes ORDER BY created_at DESC');
|
||||||
|
return stmt.all() as Recipe[];
|
||||||
|
}
|
||||||
|
|
||||||
|
findById(id: number): Recipe | undefined {
|
||||||
|
const stmt = this.db.prepare('SELECT * FROM recipes WHERE id = ?');
|
||||||
|
return stmt.get(id) as Recipe | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
### When Things Go Wrong
|
||||||
|
|
||||||
|
1. **Build errors:** Fix immediately, don't commit broken code
|
||||||
|
2. **Test failures:** Investigate, fix, re-run
|
||||||
|
3. **Stuck on implementation (>30 min):**
|
||||||
|
- Document what you tried
|
||||||
|
- Explain the blocker
|
||||||
|
- Ask Paul for guidance
|
||||||
|
4. **Unclear requirements:** Propose 2-3 options, ask Paul to choose
|
||||||
|
|
||||||
|
### Never Guess
|
||||||
|
|
||||||
|
If PROJECT.md or ARCHITECTURE.md doesn't specify:
|
||||||
|
- **Good:** "Should recipe images be stored in SQLite or filesystem? I recommend filesystem for simpler backups."
|
||||||
|
- **Bad:** Just implementing without asking
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Communication Protocol
|
||||||
|
|
||||||
|
### Progress Updates (After Each Commit)
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
✅ **Completed:** Added recipe list API endpoint with pagination
|
||||||
|
- Implemented GET /api/recipes with offset/limit
|
||||||
|
- Added integration tests (100% coverage)
|
||||||
|
- Updated API docs
|
||||||
|
|
||||||
|
**Next up:** Recipe detail view UI component
|
||||||
|
**ETA:** 1-2 hours
|
||||||
|
```
|
||||||
|
|
||||||
|
### Milestone Completion
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
🎉 **MVP Complete!**
|
||||||
|
|
||||||
|
All MVP features implemented:
|
||||||
|
- ✅ Manual recipe entry
|
||||||
|
- ✅ Recipe CRUD operations
|
||||||
|
- ✅ Tagging & search
|
||||||
|
- ✅ Cook mode with wake lock
|
||||||
|
- ✅ Docker deployment
|
||||||
|
|
||||||
|
**Test results:** 47/47 passing
|
||||||
|
**Documentation:** README, API docs, user guide updated
|
||||||
|
**Deployment:** Tested locally, ready for paje.ca
|
||||||
|
|
||||||
|
**Awaiting approval** to start v1.0 milestone (recipe scraping).
|
||||||
|
```
|
||||||
|
|
||||||
|
### Escalation (Blocked)
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
⚠️ **Blocked:** Recipe scraping strategy unclear
|
||||||
|
|
||||||
|
**Context:** Working on browser extension for recipe import. Need decision on:
|
||||||
|
|
||||||
|
1. **Puppeteer vs Cheerio?**
|
||||||
|
- Puppeteer: Handles JS-rendered sites, heavier
|
||||||
|
- Cheerio: Fast, static HTML only
|
||||||
|
|
||||||
|
2. **Where to run scraping?**
|
||||||
|
- Client-side (extension scrapes, sends JSON to API)
|
||||||
|
- Server-side (extension sends URL, server scrapes)
|
||||||
|
|
||||||
|
**Recommendation:** Cheerio for v1 (80% of sites), Puppeteer later if needed. Server-side scraping for easier updates.
|
||||||
|
|
||||||
|
**Action needed:** Paul, which approach do you prefer?
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Anti-Patterns (Don't Do This)
|
||||||
|
|
||||||
|
❌ **Committing without testing**
|
||||||
|
❌ **Changing architecture without documenting (ADR)**
|
||||||
|
❌ **Working on multiple unrelated tasks in one commit**
|
||||||
|
❌ **Ignoring linting errors "to fix later"**
|
||||||
|
❌ **Hardcoding values that should be env vars**
|
||||||
|
❌ **Skipping documentation updates**
|
||||||
|
❌ **Assuming requirements without asking**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
### Starting a new feature
|
||||||
|
```bash
|
||||||
|
git pull origin main
|
||||||
|
git checkout -b feat/recipe-scaling
|
||||||
|
# ... code ...
|
||||||
|
npm test
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: add recipe serving size scaling"
|
||||||
|
git push origin feat/recipe-scaling
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running tests
|
||||||
|
```bash
|
||||||
|
npm test # All tests
|
||||||
|
npm test -- RecipeService # Specific file
|
||||||
|
npm run test:coverage # Coverage report
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building & deploying
|
||||||
|
```bash
|
||||||
|
docker-compose build # Build containers
|
||||||
|
docker-compose up -d # Start services
|
||||||
|
docker-compose logs -f # Watch logs
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Success Metrics
|
||||||
|
|
||||||
|
You're doing it right if:
|
||||||
|
- ✅ Every commit is small, focused, tested
|
||||||
|
- ✅ Paul wakes up to completed features, not questions
|
||||||
|
- ✅ Tests pass consistently
|
||||||
|
- ✅ Documentation stays current
|
||||||
|
- ✅ Code is readable (you're writing for future-you)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_Remember: You're not just writing code—you're building a product Paul's family will use. Quality matters._
|
||||||
|
|
@ -0,0 +1,266 @@
|
||||||
|
# Recipe Manager — Architecture
|
||||||
|
|
||||||
|
**Last Updated:** 2026-03-23
|
||||||
|
**Status:** Initial Design
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tech Stack
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
- **Runtime:** Node.js 22+
|
||||||
|
- **Language:** TypeScript 5+
|
||||||
|
- **Framework:** Express.js (REST API)
|
||||||
|
- **Database:** SQLite 3 (better-sqlite3 for sync operations)
|
||||||
|
- **Validation:** Zod (schema validation)
|
||||||
|
- **Testing:** Vitest (unit), Supertest (integration)
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
- **Framework:** React 18+
|
||||||
|
- **Build Tool:** Vite
|
||||||
|
- **Routing:** React Router 6
|
||||||
|
- **State:** React Context + hooks (Zustand if needed)
|
||||||
|
- **Forms:** React Hook Form
|
||||||
|
- **Styling:** Tailwind CSS
|
||||||
|
- **Testing:** Vitest + Testing Library
|
||||||
|
|
||||||
|
### DevOps
|
||||||
|
- **Containerization:** Docker + Docker Compose
|
||||||
|
- **Reverse Proxy:** Caddy (auto-HTTPS, simple config)
|
||||||
|
- **Process Manager:** PM2 (for non-Docker deployments)
|
||||||
|
- **Backup:** Litestream (continuous SQLite replication)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture Patterns
|
||||||
|
|
||||||
|
### 1. Layered Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────┐
|
||||||
|
│ Frontend (React) │
|
||||||
|
│ Components → Hooks → API Client │
|
||||||
|
└──────────────┬──────────────────────┘
|
||||||
|
│ HTTP/JSON
|
||||||
|
┌──────────────┴──────────────────────┐
|
||||||
|
│ Backend (Express) │
|
||||||
|
│ Routes → Services → Repositories │
|
||||||
|
└──────────────┬──────────────────────┘
|
||||||
|
│ SQL
|
||||||
|
┌──────────────┴──────────────────────┐
|
||||||
|
│ Database (SQLite) │
|
||||||
|
│ recipes, tags, collections │
|
||||||
|
└─────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. API Design
|
||||||
|
|
||||||
|
**RESTful endpoints:**
|
||||||
|
- `GET /api/recipes` — List recipes (with filters, pagination)
|
||||||
|
- `GET /api/recipes/:id` — Get single recipe
|
||||||
|
- `POST /api/recipes` — Create recipe
|
||||||
|
- `PUT /api/recipes/:id` — Update recipe
|
||||||
|
- `DELETE /api/recipes/:id` — Delete recipe
|
||||||
|
- `GET /api/tags` — List tags
|
||||||
|
- `POST /api/recipes/:id/tags` — Add tag to recipe
|
||||||
|
|
||||||
|
**Response format:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"data": { ... },
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Data Model
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE recipes (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
ingredients TEXT NOT NULL, -- JSON array
|
||||||
|
instructions TEXT NOT NULL, -- JSON array of steps
|
||||||
|
source_url TEXT,
|
||||||
|
notes TEXT,
|
||||||
|
servings INTEGER,
|
||||||
|
prep_time_minutes INTEGER,
|
||||||
|
cook_time_minutes INTEGER,
|
||||||
|
created_at INTEGER NOT NULL, -- Unix timestamp
|
||||||
|
updated_at INTEGER NOT NULL,
|
||||||
|
last_cooked_at INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE tags (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT UNIQUE NOT NULL,
|
||||||
|
color TEXT -- Hex color for UI
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE recipe_tags (
|
||||||
|
recipe_id INTEGER NOT NULL,
|
||||||
|
tag_id INTEGER NOT NULL,
|
||||||
|
PRIMARY KEY (recipe_id, tag_id),
|
||||||
|
FOREIGN KEY (recipe_id) REFERENCES recipes(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_recipes_title ON recipes(title);
|
||||||
|
CREATE INDEX idx_recipes_created_at ON recipes(created_at DESC);
|
||||||
|
CREATE INDEX idx_recipe_tags_recipe ON recipe_tags(recipe_id);
|
||||||
|
CREATE INDEX idx_recipe_tags_tag ON recipe_tags(tag_id);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Frontend Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── components/
|
||||||
|
│ ├── RecipeCard.tsx
|
||||||
|
│ ├── RecipeForm.tsx
|
||||||
|
│ ├── RecipeDetail.tsx
|
||||||
|
│ ├── CookMode.tsx
|
||||||
|
│ └── SearchBar.tsx
|
||||||
|
├── hooks/
|
||||||
|
│ ├── useRecipes.ts
|
||||||
|
│ ├── useRecipe.ts
|
||||||
|
│ └── useTags.ts
|
||||||
|
├── services/
|
||||||
|
│ └── api.ts -- API client
|
||||||
|
├── types/
|
||||||
|
│ └── recipe.ts -- TypeScript interfaces
|
||||||
|
├── pages/
|
||||||
|
│ ├── HomePage.tsx
|
||||||
|
│ ├── RecipeListPage.tsx
|
||||||
|
│ ├── RecipeDetailPage.tsx
|
||||||
|
│ └── CookModePage.tsx
|
||||||
|
├── App.tsx
|
||||||
|
└── main.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key Decisions
|
||||||
|
|
||||||
|
### Why better-sqlite3 over node-sqlite3?
|
||||||
|
- Synchronous API (simpler error handling)
|
||||||
|
- Faster performance (native bindings)
|
||||||
|
- Better TypeScript support
|
||||||
|
|
||||||
|
### Why Tailwind CSS?
|
||||||
|
- Rapid prototyping
|
||||||
|
- Agent-friendly (well-documented utility classes)
|
||||||
|
- No CSS-in-JS overhead
|
||||||
|
|
||||||
|
### Why Vite over Create-React-App?
|
||||||
|
- Faster dev server (ESM-native)
|
||||||
|
- Simpler config
|
||||||
|
- Better TypeScript support
|
||||||
|
|
||||||
|
### Why Docker Compose?
|
||||||
|
- Consistent dev/prod environment
|
||||||
|
- Easy to add services (reverse proxy, backup)
|
||||||
|
- Paul already uses Docker for fintrove
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
### 1. Agent Iteration Loop
|
||||||
|
```bash
|
||||||
|
# Agent reads PROJECT.md + ARCHITECTURE.md
|
||||||
|
# Agent plans next feature
|
||||||
|
# Agent implements + tests
|
||||||
|
# Agent commits with conventional commit message
|
||||||
|
# Agent updates docs/ADR-xxx.md
|
||||||
|
# Agent reports completion
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Testing Strategy
|
||||||
|
- **Unit tests:** Core business logic (recipe parsing, scaling calculations)
|
||||||
|
- **Integration tests:** API endpoints
|
||||||
|
- **E2E tests:** Critical user flows (create recipe → cook mode)
|
||||||
|
|
||||||
|
### 3. Commit Conventions
|
||||||
|
```
|
||||||
|
feat: add recipe scaling
|
||||||
|
fix: correct ingredient parsing
|
||||||
|
docs: update architecture decisions
|
||||||
|
test: add cook mode E2E tests
|
||||||
|
chore: bump dependencies
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### Docker Compose Stack
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
recipe-manager:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
volumes:
|
||||||
|
- ./data:/app/data # SQLite database
|
||||||
|
environment:
|
||||||
|
NODE_ENV: production
|
||||||
|
DATABASE_PATH: /app/data/recipes.db
|
||||||
|
|
||||||
|
caddy:
|
||||||
|
image: caddy:2
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ./Caddyfile:/etc/caddy/Caddyfile
|
||||||
|
- caddy_data:/data
|
||||||
|
depends_on:
|
||||||
|
- recipe-manager
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
caddy_data:
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup Strategy
|
||||||
|
- **Litestream:** Continuous replication to S3/B2
|
||||||
|
- **Manual exports:** Weekly JSON dumps for portability
|
||||||
|
- **Git LFS:** Track database snapshots (optional)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
### MVP (Single Household)
|
||||||
|
- No authentication (behind home network or VPN)
|
||||||
|
- HTTPS via Caddy (Let's Encrypt)
|
||||||
|
- Input validation (prevent SQL injection via Zod)
|
||||||
|
|
||||||
|
### Future (Multi-User)
|
||||||
|
- JWT-based auth
|
||||||
|
- Per-user recipe collections
|
||||||
|
- Invite-only signup
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance Goals
|
||||||
|
|
||||||
|
- **Page load:** <1s on 3G connection
|
||||||
|
- **Recipe search:** <100ms for 1000 recipes
|
||||||
|
- **Cook mode:** Wake lock prevents screen sleep
|
||||||
|
- **Offline support:** Service worker (PWA) in v1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Open Questions for Agents
|
||||||
|
|
||||||
|
1. **Recipe scraping:** Puppeteer vs Playwright vs Cheerio?
|
||||||
|
2. **Image storage:** Filesystem vs base64 in DB vs S3?
|
||||||
|
3. **Serving size scaling:** Fractional math library needed?
|
||||||
|
4. **Export format:** JSON, CSV, or standard (Recipe Schema.org)?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_Agents: Add Architecture Decision Records (ADRs) in `docs/` as you make significant choices._
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
# Recipe Manager — Project Vision
|
||||||
|
|
||||||
|
**Project Name:** Recipe Manager
|
||||||
|
**Owner:** Paul Huliganga
|
||||||
|
**Created:** 2026-03-23
|
||||||
|
**Status:** Planning → MVP Development
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Vision
|
||||||
|
|
||||||
|
Build a **self-hosted, privacy-first recipe management app** that Anne and Elizabeth can use to organize, import, and cook from their recipes—replacing CopyMeThat with full data ownership and extensibility.
|
||||||
|
|
||||||
|
### Why Build This?
|
||||||
|
|
||||||
|
1. **Data sovereignty** — We control our data, not a SaaS provider
|
||||||
|
2. **Agentic engineering practice** — Perfect scope for autonomous agent-driven development
|
||||||
|
3. **Extensibility** — Future AI features (meal planning, cost tracking via Fintrove integration)
|
||||||
|
4. **Learning** — Hands-on experience with modern web stack + agent collaboration
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
|
||||||
|
### MVP (v0.1) — "Anne and Elizabeth can use it"
|
||||||
|
- ✅ Manual recipe entry (title, ingredients, instructions, source URL, notes)
|
||||||
|
- ✅ Recipe viewing/editing/deletion
|
||||||
|
- ✅ Basic organization (tags/collections)
|
||||||
|
- ✅ Search (text-based)
|
||||||
|
- ✅ Cook mode (ingredient checkboxes, step tracking, wake lock)
|
||||||
|
- ✅ Self-hosted deployment (Docker Compose on paje.ca)
|
||||||
|
|
||||||
|
### v1.0 — "Feature parity with CopyMeThat"
|
||||||
|
- Recipe scraping (browser extension or bookmarklet)
|
||||||
|
- Multi-device sync
|
||||||
|
- Print styles
|
||||||
|
- Scaling (adjust serving sizes)
|
||||||
|
- Random recipe suggestion
|
||||||
|
|
||||||
|
### v2.0 — "AI-enhanced"
|
||||||
|
- Ingredient substitution suggestions
|
||||||
|
- Meal planning
|
||||||
|
- Shopping list generation
|
||||||
|
- Integration with Fintrove (recipe cost tracking)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constraints
|
||||||
|
|
||||||
|
### Technical
|
||||||
|
- **Stack:** Node.js + TypeScript + React + SQLite
|
||||||
|
- **Deployment:** Docker Compose, self-hosted on paje.ca
|
||||||
|
- **Storage:** Local-first (SQLite), cloud sync optional in v1
|
||||||
|
- **Browser support:** Modern evergreen browsers (Chrome, Firefox, Safari, Edge)
|
||||||
|
|
||||||
|
### Development
|
||||||
|
- **Agent-driven:** Sub-agents build, test, document autonomously
|
||||||
|
- **Version control:** Git with conventional commits
|
||||||
|
- **Testing:** Unit tests for core logic, E2E tests for critical flows
|
||||||
|
- **Documentation:** Auto-generated architecture decision records (ADRs)
|
||||||
|
|
||||||
|
### Timeline
|
||||||
|
- **MVP:** 48-72 hours of agent work (overnight runs)
|
||||||
|
- **v1.0:** 1-2 weeks (incremental agent iterations)
|
||||||
|
- **v2.0:** TBD (depends on AI integration complexity)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Non-Goals (for MVP)
|
||||||
|
|
||||||
|
- ❌ Mobile apps (web-first, PWA later)
|
||||||
|
- ❌ User authentication (single household deployment)
|
||||||
|
- ❌ Recipe sharing/community features
|
||||||
|
- ❌ Video support
|
||||||
|
- ❌ Nutrition tracking (maybe v2)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key Decisions
|
||||||
|
|
||||||
|
### Why SQLite?
|
||||||
|
- Local-first, zero-config, portable
|
||||||
|
- Perfect for single-household deployment
|
||||||
|
- Can sync via file replication (Syncthing, Dropbox) if needed
|
||||||
|
|
||||||
|
### Why React?
|
||||||
|
- Agent familiarity (Codex knows React cold)
|
||||||
|
- Rich ecosystem for forms, UI components
|
||||||
|
- Can evolve to Next.js if SSR needed
|
||||||
|
|
||||||
|
### Why Docker Compose?
|
||||||
|
- Consistent deployment across machines
|
||||||
|
- Easy backup/restore (just copy SQLite file)
|
||||||
|
- Can add services incrementally (reverse proxy, backup cron, etc.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Agent Instructions Reference
|
||||||
|
|
||||||
|
See `AGENT_INSTRUCTIONS.md` for how agents should approach development, testing, and documentation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Questions for Paul
|
||||||
|
|
||||||
|
1. **Domain/URL:** Should this live at `recipes.paje.ca` or subdirectory?
|
||||||
|
2. **Initial users:** Just Anne and Elizabeth, or open to friends/family?
|
||||||
|
3. **Data migration:** Export from CopyMeThat, or start fresh?
|
||||||
|
4. **First priority after MVP:** Scraping extension or AI features?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_This is a living document. Agents should update it as the project evolves._
|
||||||
|
|
@ -0,0 +1,301 @@
|
||||||
|
# Recipe Manager
|
||||||
|
|
||||||
|
**Self-hosted, privacy-first recipe management app**
|
||||||
|
|
||||||
|
Built with ❤️ by autonomous AI agents for the Huliganga family.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
🚧 **In Development** — MVP phase
|
||||||
|
📋 See [ROADMAP.md](ROADMAP.md) for current milestone
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What Is This?
|
||||||
|
|
||||||
|
A modern, self-hosted alternative to services like CopyMeThat. Store, organize, and cook from your recipes with full data ownership.
|
||||||
|
|
||||||
|
### Key Features (MVP)
|
||||||
|
- ✅ Manual recipe entry
|
||||||
|
- ✅ Tag-based organization
|
||||||
|
- ✅ Text search
|
||||||
|
- ✅ Cook mode (ingredient checklist + step tracking)
|
||||||
|
- ✅ Self-hosted deployment (Docker)
|
||||||
|
|
||||||
|
### Planned Features
|
||||||
|
- Recipe scraping (browser extension)
|
||||||
|
- Serving size scaling
|
||||||
|
- Meal planning & shopping lists
|
||||||
|
- AI-powered ingredient substitutions
|
||||||
|
- Integration with Fintrove (cost tracking)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
- Node.js 22+
|
||||||
|
- Docker & Docker Compose (for deployment)
|
||||||
|
- npm or pnpm
|
||||||
|
|
||||||
|
### Development Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone the repo
|
||||||
|
cd /home/paulh/.openclaw/workspace/projects/recipe-manager
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# Start backend (development mode)
|
||||||
|
npm run dev:backend
|
||||||
|
|
||||||
|
# Start frontend (separate terminal)
|
||||||
|
npm run dev:frontend
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Production Deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build and start containers
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
docker-compose logs -f
|
||||||
|
|
||||||
|
# Stop
|
||||||
|
docker-compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
Access at `http://localhost:3000` (or `https://recipes.paje.ca` in production).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
recipe-manager/
|
||||||
|
├── src/
|
||||||
|
│ ├── backend/ # Express API
|
||||||
|
│ │ ├── routes/ # API endpoints
|
||||||
|
│ │ ├── services/ # Business logic
|
||||||
|
│ │ ├── repositories/ # Database access
|
||||||
|
│ │ └── types/ # TypeScript types
|
||||||
|
│ ├── frontend/ # React app
|
||||||
|
│ │ ├── components/ # UI components
|
||||||
|
│ │ ├── hooks/ # React hooks
|
||||||
|
│ │ ├── pages/ # Route pages
|
||||||
|
│ │ └── services/ # API client
|
||||||
|
│ └── shared/ # Shared types/utilities
|
||||||
|
├── tests/
|
||||||
|
│ ├── unit/ # Unit tests
|
||||||
|
│ ├── integration/ # API integration tests
|
||||||
|
│ └── e2e/ # End-to-end tests
|
||||||
|
├── docs/
|
||||||
|
│ ├── api.md # API documentation
|
||||||
|
│ ├── user-guide.md # User manual
|
||||||
|
│ └── ADR-*.md # Architecture decision records
|
||||||
|
├── data/ # SQLite database (gitignored)
|
||||||
|
├── PROJECT.md # Product vision
|
||||||
|
├── ARCHITECTURE.md # Technical design
|
||||||
|
├── ROADMAP.md # Development milestones
|
||||||
|
├── AGENT_INSTRUCTIONS.md # How agents work on this project
|
||||||
|
└── docker-compose.yml # Deployment config
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technology Stack
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
- **Node.js** + **TypeScript** — Modern, type-safe JavaScript
|
||||||
|
- **Express** — Minimal, flexible web framework
|
||||||
|
- **SQLite** (better-sqlite3) — Fast, embedded database
|
||||||
|
- **Zod** — Runtime type validation
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
- **React 18** — Component-based UI
|
||||||
|
- **Vite** — Lightning-fast dev server
|
||||||
|
- **Tailwind CSS** — Utility-first styling
|
||||||
|
- **React Router** — Client-side routing
|
||||||
|
|
||||||
|
### DevOps
|
||||||
|
- **Docker Compose** — Container orchestration
|
||||||
|
- **Caddy** — Reverse proxy with auto-HTTPS
|
||||||
|
- **Vitest** — Fast, modern test runner
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- [Project Vision](PROJECT.md) — Why we're building this
|
||||||
|
- [Architecture Guide](ARCHITECTURE.md) — Technical decisions & patterns
|
||||||
|
- [Roadmap](ROADMAP.md) — Planned features & milestones
|
||||||
|
- [Agent Instructions](AGENT_INSTRUCTIONS.md) — How AI agents contribute
|
||||||
|
- [API Docs](docs/api.md) — Endpoint reference *(coming soon)*
|
||||||
|
- [User Guide](docs/user-guide.md) — How to use the app *(coming soon)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
This project is built **agent-first** using OpenClaw autonomous agents:
|
||||||
|
|
||||||
|
1. **Agent reads context** — PROJECT.md, ARCHITECTURE.md, ROADMAP.md
|
||||||
|
2. **Agent picks next task** — From the current milestone
|
||||||
|
3. **Agent implements & tests** — Following coding standards
|
||||||
|
4. **Agent commits & documents** — Conventional commits + ADRs
|
||||||
|
5. **Agent reports completion** — Or escalates if blocked
|
||||||
|
|
||||||
|
Human oversight at milestone boundaries.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
This is a personal/family project, but contributions welcome!
|
||||||
|
|
||||||
|
### For Humans
|
||||||
|
1. Read [PROJECT.md](PROJECT.md) and [ARCHITECTURE.md](ARCHITECTURE.md)
|
||||||
|
2. Check [ROADMAP.md](ROADMAP.md) for open tasks
|
||||||
|
3. Follow patterns in [AGENT_INSTRUCTIONS.md](AGENT_INSTRUCTIONS.md)
|
||||||
|
4. Submit PRs with tests + documentation
|
||||||
|
|
||||||
|
### For AI Agents
|
||||||
|
Read [AGENT_INSTRUCTIONS.md](AGENT_INSTRUCTIONS.md) — it's your operating manual.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run all tests
|
||||||
|
npm test
|
||||||
|
|
||||||
|
# Run tests in watch mode
|
||||||
|
npm run test:watch
|
||||||
|
|
||||||
|
# Generate coverage report
|
||||||
|
npm run test:coverage
|
||||||
|
|
||||||
|
# Run specific test file
|
||||||
|
npm test -- RecipeService.test.ts
|
||||||
|
|
||||||
|
# E2E tests (requires app running)
|
||||||
|
npm run test:e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
**Coverage goal:** >80% on core business logic.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### Local Development
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
Access at http://localhost:5173 (frontend) and http://localhost:3000 (API).
|
||||||
|
|
||||||
|
### Production (paje.ca)
|
||||||
|
```bash
|
||||||
|
# On server
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# Check status
|
||||||
|
docker-compose ps
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
docker-compose logs -f recipe-manager
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup & Restore
|
||||||
|
```bash
|
||||||
|
# Backup database
|
||||||
|
cp data/recipes.db data/recipes-backup-$(date +%Y%m%d).db
|
||||||
|
|
||||||
|
# Restore
|
||||||
|
cp data/recipes-backup-20260323.db data/recipes.db
|
||||||
|
docker-compose restart
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
Create `.env` file:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Backend
|
||||||
|
NODE_ENV=production
|
||||||
|
PORT=3000
|
||||||
|
DATABASE_PATH=/app/data/recipes.db
|
||||||
|
|
||||||
|
# Frontend (build-time)
|
||||||
|
VITE_API_URL=https://recipes.paje.ca/api
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Database locked
|
||||||
|
```bash
|
||||||
|
# Check for stale locks
|
||||||
|
fuser data/recipes.db
|
||||||
|
# Kill if needed, then restart
|
||||||
|
docker-compose restart
|
||||||
|
```
|
||||||
|
|
||||||
|
### Port already in use
|
||||||
|
```bash
|
||||||
|
# Find process using port 3000
|
||||||
|
lsof -i :3000
|
||||||
|
# Kill it
|
||||||
|
kill -9 <PID>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tests failing
|
||||||
|
```bash
|
||||||
|
# Clear node_modules and reinstall
|
||||||
|
rm -rf node_modules package-lock.json
|
||||||
|
npm install
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Private project — All rights reserved (for now).
|
||||||
|
May open-source later.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
**Product Owner:** Paul Huliganga
|
||||||
|
**Primary Users:** Anne & Elizabeth
|
||||||
|
**Development:** Autonomous AI agents (Codex 5.2) via OpenClaw
|
||||||
|
**Human Oversight:** Paul
|
||||||
|
|
||||||
|
Built as a learning project for agentic engineering and modern web development.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Roadmap Highlights
|
||||||
|
|
||||||
|
- **MVP (v0.1):** Manual entry, tags, search, cook mode ← *You are here*
|
||||||
|
- **v1.0:** Recipe scraping, advanced search, multi-device sync
|
||||||
|
- **v2.0:** AI features (meal planning, cost tracking, substitutions)
|
||||||
|
|
||||||
|
See [ROADMAP.md](ROADMAP.md) for details.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Questions?** Check [docs/](docs/) or ask Paul.
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
# Recipe Manager — Product Roadmap
|
||||||
|
|
||||||
|
**Last Updated:** 2026-03-23
|
||||||
|
**Approach:** Agent-driven incremental releases
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Philosophy
|
||||||
|
|
||||||
|
Each release is **shippable and usable** — no partial features. Agents propose milestones, Paul approves, agents build autonomously.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MVP (v0.1) — "It Works!"
|
||||||
|
|
||||||
|
**Goal:** Anne and Elizabeth can create, organize, and cook from recipes
|
||||||
|
**Timeline:** 48-72 hours of agent work
|
||||||
|
**Deliverables:**
|
||||||
|
|
||||||
|
### Core Features
|
||||||
|
- ✅ **Manual recipe entry** — Form with title, ingredients (list), instructions (steps), source URL, notes
|
||||||
|
- ✅ **Recipe list view** — Cards with title, description, tags
|
||||||
|
- ✅ **Recipe detail view** — Full recipe with edit/delete buttons
|
||||||
|
- ✅ **Basic tagging** — Add/remove tags (Dessert, Main Course, Quick, etc.)
|
||||||
|
- ✅ **Text search** — Filter recipes by title or ingredients
|
||||||
|
- ✅ **Cook mode** — Checklist UI for ingredients/steps, screen wake lock
|
||||||
|
|
||||||
|
### Technical
|
||||||
|
- ✅ SQLite database with schema migrations
|
||||||
|
- ✅ REST API (Express + TypeScript)
|
||||||
|
- ✅ React frontend (Vite + Tailwind)
|
||||||
|
- ✅ Docker Compose deployment
|
||||||
|
- ✅ Basic error handling + validation
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
- ✅ Unit tests for API routes
|
||||||
|
- ✅ Integration tests for database operations
|
||||||
|
- ✅ Manual smoke test checklist
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- ✅ README with setup instructions
|
||||||
|
- ✅ API documentation (endpoint specs)
|
||||||
|
- ✅ User guide (how to add/cook recipes)
|
||||||
|
|
||||||
|
### Acceptance Criteria
|
||||||
|
1. Paul can deploy locally and on paje.ca
|
||||||
|
2. Anne can add a recipe manually
|
||||||
|
3. Elizabeth can find the recipe and use cook mode
|
||||||
|
4. No data loss after container restart
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v1.0 — "Daily Driver"
|
||||||
|
|
||||||
|
**Goal:** Feature parity with CopyMeThat (minus community)
|
||||||
|
**Timeline:** 1-2 weeks (incremental agent work)
|
||||||
|
**Deliverables:**
|
||||||
|
|
||||||
|
### Recipe Import
|
||||||
|
- **Browser extension** (Chrome/Firefox) to scrape recipes from any site
|
||||||
|
- Parse Schema.org Recipe microdata
|
||||||
|
- Fallback heuristic parsing for non-standard sites
|
||||||
|
- One-click import to local instance
|
||||||
|
- **Manual URL import** — Paste URL, backend scrapes + parses
|
||||||
|
|
||||||
|
### Enhanced Organization
|
||||||
|
- **Collections** — Group recipes (Holiday, Meal Prep, Favorites)
|
||||||
|
- **Advanced search** — Filter by tags, collections, cook time, servings
|
||||||
|
- **Sorting** — By title, date added, last cooked, random
|
||||||
|
|
||||||
|
### Cook Mode Improvements
|
||||||
|
- **Horizontal tablet view** — Landscape-optimized layout
|
||||||
|
- **Serving size scaling** — Auto-adjust ingredient quantities
|
||||||
|
- **Timer integration** — Countdown timers for steps (optional)
|
||||||
|
|
||||||
|
### Sharing & Export
|
||||||
|
- **Print styles** — Minimal, card, full-page
|
||||||
|
- **Email recipe** — Send as plain text or link
|
||||||
|
- **Export to JSON** — Backup all recipes
|
||||||
|
|
||||||
|
### Sync (Optional)
|
||||||
|
- **Multi-device sync** — SQLite file sync via Syncthing or Dropbox
|
||||||
|
- **Conflict resolution** — Last-write-wins with merge log
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
- ✅ E2E tests for import + cook mode flows
|
||||||
|
- ✅ Browser extension tested on top 10 recipe sites
|
||||||
|
|
||||||
|
### Acceptance Criteria
|
||||||
|
1. Anne can import recipes from her favorite sites in <10 seconds
|
||||||
|
2. Elizabeth can scale a recipe for 8 people
|
||||||
|
3. Paul can print a recipe for offline use
|
||||||
|
4. All tests pass in CI
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v2.0 — "AI-Enhanced"
|
||||||
|
|
||||||
|
**Goal:** Smart features that make recipe management effortless
|
||||||
|
**Timeline:** TBD (depends on AI integration complexity)
|
||||||
|
**Deliverables:**
|
||||||
|
|
||||||
|
### AI Features
|
||||||
|
- **Ingredient substitutions** — Suggest alternatives based on dietary preferences or availability
|
||||||
|
- **Meal planning** — Generate weekly menus from recipe collection
|
||||||
|
- **Shopping list** — Aggregate ingredients, de-duplicate, categorize by aisle
|
||||||
|
- **Recipe recommendations** — "You haven't cooked this in 3 months, try it tonight!"
|
||||||
|
- **Nutrition estimates** — Calorie/macro breakdown via USDA database
|
||||||
|
|
||||||
|
### Fintrove Integration
|
||||||
|
- **Recipe cost tracking** — Link ingredients to grocery prices
|
||||||
|
- **Budget-aware meal plans** — Optimize for cost + nutrition + preferences
|
||||||
|
|
||||||
|
### Advanced Features
|
||||||
|
- **Voice input** — Add ingredients/steps via speech-to-text
|
||||||
|
- **OCR import** — Scan recipe cards/cookbooks
|
||||||
|
- **Recipe rating & notes** — Track favorites, add photos of results
|
||||||
|
|
||||||
|
### Mobile App (Optional)
|
||||||
|
- **React Native** or **PWA** for native mobile experience
|
||||||
|
- **Offline-first** — Sync when online
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
- ✅ AI feature accuracy benchmarks
|
||||||
|
- ✅ Load testing (1000+ recipes, complex meal plans)
|
||||||
|
|
||||||
|
### Acceptance Criteria
|
||||||
|
1. AI suggests a valid substitution for missing ingredient
|
||||||
|
2. Meal plan generation completes in <5 seconds
|
||||||
|
3. Shopping list works offline
|
||||||
|
4. Fintrove integration tracks recipe costs accurately
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Future Ideas (Backlog)
|
||||||
|
|
||||||
|
- **Community recipes** — Optional sharing with friends/family
|
||||||
|
- **Recipe version control** — Track edits over time
|
||||||
|
- **Collaborative cooking** — Multi-user cook mode (dinner party!)
|
||||||
|
- **Video tutorials** — Embed YouTube/TikTok links
|
||||||
|
- **Equipment tracking** — "Recipes you can make with Instant Pot"
|
||||||
|
- **Seasonal suggestions** — "Fall comfort food recipes"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Agent Notes
|
||||||
|
|
||||||
|
### How to Use This Roadmap
|
||||||
|
|
||||||
|
1. **Read PROJECT.md** first for vision + constraints
|
||||||
|
2. **Pick the next uncompleted milestone** (MVP → v1 → v2)
|
||||||
|
3. **Break milestone into tasks** (1-4 hour chunks)
|
||||||
|
4. **Implement ONE task at a time** — commit, test, document
|
||||||
|
5. **Update this roadmap** when milestones complete
|
||||||
|
|
||||||
|
### Decision Authority
|
||||||
|
|
||||||
|
- **Agents decide:** Implementation details, libraries, file structure
|
||||||
|
- **Paul approves:** Milestone completion, new features, major architecture changes
|
||||||
|
|
||||||
|
### Communication
|
||||||
|
|
||||||
|
- **Progress updates:** After each task completion (commit message + summary)
|
||||||
|
- **Blockers:** If stuck >30 minutes, escalate to Paul with context
|
||||||
|
- **Proposals:** New features or scope changes → document in PROJECT.md, ask Paul
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Milestone Tracking
|
||||||
|
|
||||||
|
| Milestone | Status | Started | Completed | Notes |
|
||||||
|
|-----------|--------|---------|-----------|-------|
|
||||||
|
| MVP (v0.1) | 📋 Planned | — | — | Awaiting agent kickoff |
|
||||||
|
| v1.0 | ⏳ Pending | — | — | After MVP validation |
|
||||||
|
| v2.0 | 💡 Ideas | — | — | AI integration research needed |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_This roadmap evolves as we learn. Agents: update it as you work. Paul: review and approve milestones._
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
# TODO — Recipe Manager
|
||||||
|
|
||||||
|
**Last Updated:** 2026-03-23
|
||||||
|
**Current Milestone:** MVP (v0.1)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Active Tasks
|
||||||
|
|
||||||
|
### Backend Setup
|
||||||
|
- [ ] Initialize Node.js project structure
|
||||||
|
- [ ] Set up TypeScript configuration
|
||||||
|
- [ ] Create SQLite schema with migrations
|
||||||
|
- [ ] Implement recipe CRUD API endpoints
|
||||||
|
- [ ] Add Zod validation schemas
|
||||||
|
- [ ] Write API integration tests
|
||||||
|
|
||||||
|
### Frontend Setup
|
||||||
|
- [ ] Initialize React + Vite project
|
||||||
|
- [ ] Configure Tailwind CSS
|
||||||
|
- [ ] Set up React Router
|
||||||
|
- [ ] Create recipe list page
|
||||||
|
- [ ] Create recipe detail/edit page
|
||||||
|
- [ ] Implement cook mode UI
|
||||||
|
|
||||||
|
### Features
|
||||||
|
- [ ] Tag management (create, assign, filter)
|
||||||
|
- [ ] Text search (title + ingredients)
|
||||||
|
- [ ] Screen wake lock for cook mode
|
||||||
|
- [ ] Basic error handling + loading states
|
||||||
|
|
||||||
|
### DevOps
|
||||||
|
- [ ] Create Dockerfile for backend
|
||||||
|
- [ ] Create Dockerfile for frontend (nginx)
|
||||||
|
- [ ] Write docker-compose.yml
|
||||||
|
- [ ] Test local deployment
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- [ ] Write API documentation (docs/api.md)
|
||||||
|
- [ ] Create user guide (docs/user-guide.md)
|
||||||
|
- [ ] Add setup instructions to README
|
||||||
|
- [ ] Document first architecture decisions (ADRs)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Completed Tasks
|
||||||
|
|
||||||
|
_(none yet)_
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Backlog (Post-MVP)
|
||||||
|
|
||||||
|
### v1.0
|
||||||
|
- [ ] Browser extension for recipe scraping
|
||||||
|
- [ ] Recipe scaling (adjust servings)
|
||||||
|
- [ ] Print styles
|
||||||
|
- [ ] Advanced search filters
|
||||||
|
- [ ] Random recipe suggestion
|
||||||
|
|
||||||
|
### v2.0
|
||||||
|
- [ ] AI ingredient substitutions
|
||||||
|
- [ ] Meal planning
|
||||||
|
- [ ] Shopping list generation
|
||||||
|
- [ ] Fintrove cost tracking integration
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚧 Blocked / Needs Decision
|
||||||
|
|
||||||
|
- **Recipe images:** Store in filesystem or SQLite? (Waiting for agent decision)
|
||||||
|
- **Scraping strategy:** Puppeteer vs Cheerio? (v1.0 decision)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes for Agents
|
||||||
|
|
||||||
|
- Check this file before starting work
|
||||||
|
- Move completed tasks to "Completed" section
|
||||||
|
- Add new tasks as you discover them
|
||||||
|
- Flag blockers for Paul's attention
|
||||||
|
- Keep this file current (update after each commit)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_This is your working task list. Keep it honest and up-to-date._
|
||||||
Loading…
Reference in New Issue