cardamom
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Viewing readonly version of main branch: v380View latest version
A comprehensive mobile-friendly web application that captures, parses, stores recipes from multiple sources and generates smart shopping lists from your recipe collection.
- Multi-source Recipe Input: Accept recipes from:
- Web URLs (recipe websites)
- PDF files
- Images (photos of recipes)
- Plain text input
- Intelligent Parsing: Automatically extracts:
- Dish title and description
- Ingredients with precise quantities and units
- Step-by-step cooking instructions
- Cooking metadata (prep time, cook time, servings, difficulty)
- Recipe tags and source information
- Recipe Storage: Persistent SQLite storage with full CRUD operations
- Recipe Management: View, edit, delete, and organize saved recipes
- Advanced Features:
- Recipe filtering and search
- Fraction-to-decimal conversion for precise measurements
- Comprehensive error handling and validation
- Real-time parsing feedback
- Smart Shopping List Generation: Create shopping lists from selected recipes
- Ingredient Consolidation: Automatically combines duplicate ingredients from multiple recipes
- Interactive Shopping Experience:
- Check/uncheck items as you shop
- Real-time progress tracking
- Visual progress bar showing completion percentage
- List Management:
- Edit shopping list names
- Delete completed lists
- View creation timestamps
- Ingredient Details: Shows which recipes each ingredient came from
- Mobile-Optimized: Perfect for grocery shopping on your phone
- Frontend: React 18.2.0 with TypeScript, TailwindCSS
- Backend: Hono API framework with TypeScript
- Database: SQLite with normalized schema (4 tables: recipes, ingredients, shopping_lists, shopping_list_items)
- AI: OpenAI GPT-4o-mini for intelligent recipe parsing
- File Processing:
- PDF parsing via
unpdf
library - Image OCR via OpenAI Vision API
- URL content extraction
- PDF parsing via
├── backend/
│ ├── database/
│ │ ├── migrations.ts # Database schema (4 tables)
│ │ └── queries.ts # Database operations
│ ├── routes/
│ │ ├── recipes.ts # Recipe CRUD operations
│ │ ├── parse.ts # Recipe parsing endpoints
│ │ └── shopping-lists.ts # Shopping list operations
│ └── index.ts # Main API entry point
├── frontend/
│ ├── components/
│ │ ├── App.tsx # Main app component
│ │ ├── RecipeForm.tsx # Recipe input form
│ │ ├── RecipeList.tsx # Recipe listing
│ │ ├── RecipeView.tsx # Individual recipe display
│ │ ├── ShoppingListCreator.tsx # Create shopping lists
│ │ ├── ShoppingListList.tsx # Shopping list overview
│ │ └── ShoppingListView.tsx # Interactive shopping list
│ ├── index.html # Main HTML template
│ └── index.tsx # Frontend entry point
└── shared/
├── types.ts # Shared TypeScript types
└── utils.ts # Shared utility functions
GET /api/recipes
- Get all recipes (supports filtering via query params)?search=term
- Search in recipe titles and descriptions?difficulty=easy|medium|hard
- Filter by difficulty?maxPrepTime=minutes
- Filter by maximum prep time?maxCookTime=minutes
- Filter by maximum cook time?tags=tag1,tag2
- Filter by tags
POST /api/recipes
- Save a new recipeGET /api/recipes/:id
- Get specific recipe by IDPUT /api/recipes/:id
- Update existing recipeDELETE /api/recipes/:id
- Delete recipe
POST /api/parse/url
- Parse recipe from web URLPOST /api/parse/pdf
- Parse recipe from PDF file (base64)POST /api/parse/image
- Parse recipe from image (base64)POST /api/parse/text
- Parse recipe from plain text
GET /api/shopping-lists
- Get all shopping listsPOST /api/shopping-lists
- Create shopping list from recipe IDsGET /api/shopping-lists/:id
- Get specific shopping listPUT /api/shopping-lists/:id
- Update shopping list nameDELETE /api/shopping-lists/:id
- Delete shopping listPUT /api/shopping-lists/items/:id
- Update shopping list item (check/uncheck)
GET /api/health
- Health check endpointGET /api/test-delete
- Test endpoint for debugging delete operations
- Access the App: Open the application in your browser
- Add Recipes: Choose from multiple input methods:
- URL: Paste a recipe website URL
- PDF: Upload a PDF file containing a recipe
- Image: Upload a photo of a recipe
- Text: Paste or type recipe text directly
- Review & Edit: The AI will parse the recipe automatically - review and edit as needed
- Save: Add the recipe to your collection
- Manage: View, search, filter, edit, or delete saved recipes
- Select Recipes: From your recipe collection, choose recipes you want to cook
- Generate List: Click "Create Shopping List" to automatically generate a consolidated shopping list
- Shop Smart: Use the interactive shopping list on your phone:
- Check off items as you shop
- See real-time progress
- View which recipes each ingredient is for
- Manage Lists: Edit list names, delete completed lists, track shopping history
The app uses a normalized SQLite database with four main tables:
id
- Primary keytitle
- Recipe name (required)description
- Optional descriptionservings
,prep_time
,cook_time
- Numeric metadatadifficulty
- Enum: 'easy', 'medium', 'hard'tags
- JSON array of tag stringssource
- Source URL or descriptionimage_url
- Optional recipe image URLsteps
- JSON array of cooking stepscreated_at
,updated_at
- Timestamps
id
- Primary keyrecipe_id
- Foreign key to recipes tablename
- Ingredient name (required)amount
- Quantity as string (required)unit
- Measurement unit (required)notes
- Optional ingredient notesorder_index
- For maintaining ingredient order
id
- Primary keyname
- Shopping list namecreated_at
,updated_at
- Timestamps
id
- Primary keyshopping_list_id
- Foreign key to shopping lists tablename
- Ingredient nameamount
- Consolidated quantityunit
- Measurement unitnotes
- Optional noteschecked
- Boolean for shopping progressrecipe_ids
- JSON array tracking source recipesorder_index
- For maintaining item order
- Uses OpenAI GPT-4o-mini for intelligent content extraction
- Handles fractional Unicode characters (¼, ½, ¾) and converts to decimals
- Robust JSON extraction with fallback parsing
- Comprehensive validation and data cleaning
- Ingredient Consolidation: Automatically combines duplicate ingredients across recipes
- Recipe Tracking: Maintains links between shopping list items and source recipes
- Progress Tracking: Real-time completion percentage and visual progress bars
- Mobile-Optimized Interface: Touch-friendly checkboxes and responsive design
- PDF: Uses
unpdf
library for text extraction - Images: Leverages OpenAI Vision API for OCR
- URLs: Fetches and parses HTML content
- Text: Direct text processing
- Single-page React application with TypeScript
- Component-based architecture with clear separation of concerns
- Mobile-first responsive design with TailwindCSS
- Real-time error handling and loading states
- Multi-view navigation (recipes, shopping lists, forms)
- Hono-based REST API with TypeScript
- Normalized database design with proper foreign key relationships
- Comprehensive error handling and validation
- Database migrations with versioned table names
- Performance optimizations with database indexes
- Platform: Val Town (Deno runtime)
- Node.js APIs: Not required (uses Deno-compatible libraries)
- Environment Variables:
- OpenAI API key (automatically provided by Val Town's OpenAI integration)
- TypeScript: Configured via
deno.json
with Val Town types - Dependencies: All imports use ESM.sh for browser/server compatibility
- Static Files: Served via Val Town's utility functions (
serveFile
,readFile
)
- Database Changes: Update table names (e.g.,
_v1
→_v2
) when modifying schemas - Testing: Use built-in test endpoints and browser developer tools
- Debugging: Check Val Town logs for server-side issues
- Deployment: Automatic on file save in Val Town environment
- PDF Parsing Fails: Ensure PDF contains readable text (not scanned images)
- Image Upload Issues: Verify image is properly base64 encoded
- Database Errors: Check if migrations ran successfully on startup
- OpenAI Errors: Verify API quota and model availability
- Shopping List Issues: Ensure recipes have valid ingredients before creating lists
GET /api/health
- Check if API is respondingGET /api/test-delete
- Test database delete operations- Browser console logs for client-side debugging
- Server logs in Val Town interface for backend issues
This app has evolved from a simple recipe parser to a comprehensive recipe and shopping list management system. The shopping list feature represents a major enhancement that transforms the app from a recipe storage tool into a complete cooking workflow solution.