# Basil 🌿 A modern, full-stack recipe manager with web and mobile support. Import recipes from any URL, manage your recipe collection, and access them from anywhere. ## Features - **Recipe Import**: Automatically import recipes from URLs using schema.org markup - Add tags during import for instant organization - Works with 600+ supported recipe sites plus any site with schema.org markup - Preview recipe before saving with immediate tag management - **Full Recipe Management**: Create, read, update, and delete recipes - **Rich Recipe Data**: Store ingredients, instructions, prep/cook times, servings, images, and more - **Tag Organization**: Quick tagging system with autocomplete for rapid recipe organization - Add/remove tags inline on recipe detail view - Tag recipes during import - Filter recipes by tags - **Recipe Scaling**: Adjust serving sizes with automatic ingredient scaling - **Cookbooks**: Organize recipes into collections with auto-filtering by tags and categories - **Search & Filter**: Find recipes by title, cuisine, category, or tags - **Multiple Images**: Add multiple images to each recipe - **User Authentication**: Secure multi-user support with email/password and OAuth - **Backup & Restore**: Complete data backup including recipes, cookbooks, and images - **Flexible Storage**: Local filesystem storage by default, optional S3 support - **Docker Support**: Easy deployment with Docker Compose - **API-First Design**: RESTful API for web and future mobile apps ## Tech Stack - **Backend**: Node.js, TypeScript, Express, Prisma ORM, PostgreSQL - **Frontend**: React, TypeScript, Vite, React Router - **Infrastructure**: Docker, Docker Compose, nginx - **Monorepo**: npm workspaces with shared types ## Quick Start ### Prerequisites - Node.js 20+ - PostgreSQL 16+ (or use Docker) - Python 3.x with pip (for recipe scraper) - Docker (optional, for containerized deployment) **Python Dependencies:** The recipe import feature requires Python 3 and the `recipe-scrapers` package: ```bash pip3 install recipe-scrapers ``` For Docker deployments, Python dependencies are automatically installed in the container. ### Development Setup 1. **Clone the repository** ```bash git clone cd basil ``` 2. **Install dependencies** ```bash npm install ``` 3. **Set up environment variables** ```bash cp packages/api/.env.example packages/api/.env # Edit packages/api/.env with your database credentials ``` 4. **Start PostgreSQL** (if not using Docker) ```bash # Create a database named 'basil' createdb basil ``` 5. **Run database migrations** ```bash cd packages/api npm run prisma:migrate npm run prisma:generate cd ../.. ``` 6. **Start development servers** ```bash npm run dev ``` This starts: - API server at http://localhost:3001 - Web frontend at http://localhost:5173 ### Docker Deployment For production or easy local setup: ```bash # Start all services docker-compose up -d # View logs docker-compose logs -f # Stop services docker-compose down ``` Services will be available at: - Web: http://localhost:5173 - API: http://localhost:3001 - PostgreSQL: localhost:5432 ## Project Structure ``` basil/ ├── packages/ │ ├── api/ # Backend API server │ │ ├── prisma/ # Database schema and migrations │ │ └── src/ # Express routes, services, config │ ├── web/ # React web application │ │ └── src/ # Components, pages, services │ └── shared/ # Shared TypeScript types ├── docker-compose.yml └── package.json # Workspace root ``` ## Usage ### Importing a Recipe 1. Navigate to "Import Recipe" in the web app 2. Paste a recipe URL (supports 600+ sites including AllRecipes, Food Network, King Arthur Baking, etc.) 3. Click "Import Recipe" to fetch and parse the recipe 4. Preview the imported recipe details 5. Add tags using the quick tag input at the top (with autocomplete) 6. Press Enter after each tag for rapid multi-tag addition 7. Save to your collection The recipe importer works with any website that uses schema.org Recipe markup, even if not officially supported by recipe-scrapers. ### Managing Tags **Quick Tag Management:** - On recipe detail pages, use the inline tag input next to the servings adjuster - Press Enter after typing each tag for rapid multi-tag addition - Focus stays in the input field for quick consecutive tagging - Autocomplete suggests existing tags as you type - Click the × button on any tag to remove it **Tag-based Organization:** - Filter recipe list by tag name - Use tags to organize recipes by cuisine, meal type, dietary restrictions, etc. - Tags are automatically created when first used - Rename or delete unused tags from the Tags page ### API Examples **Import recipe from URL:** ```bash curl -X POST http://localhost:3001/api/recipes/import \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com/recipe"}' ``` **Get all recipes:** ```bash curl http://localhost:3001/api/recipes ``` **Create a recipe:** ```bash curl -X POST http://localhost:3001/api/recipes \ -H "Content-Type: application/json" \ -d '{ "title": "Chocolate Chip Cookies", "ingredients": [ {"name": "flour", "amount": "2", "unit": "cups", "order": 0} ], "instructions": [ {"step": 1, "text": "Preheat oven to 350°F"} ], "tags": ["dessert", "cookies", "quick"] }' ``` **Update recipe tags:** ```bash curl -X PUT http://localhost:3001/api/recipes/:id \ -H "Content-Type: application/json" \ -d '{ "tags": ["italian", "dinner", "vegetarian"] }' ``` **Filter recipes by tag:** ```bash curl http://localhost:3001/api/recipes?tag=dessert ``` ## Testing Basil includes comprehensive test coverage with unit and integration tests: ```bash # Run all tests npm test # Run tests with coverage report cd packages/api npm run test -- --coverage # Run specific test file npx vitest run src/routes/recipes.routes.test.ts ``` ### Test Coverage - **Overall**: 77.6% coverage - **Routes**: 84% coverage - recipes.routes.ts: 87% - tags.routes.ts: 92% - cookbooks.routes.ts: 88% - backup.routes.ts: 74% - auth.routes.ts: 37% - **Services**: 66% coverage - **Utils**: 100% coverage Test suite includes: - 377+ passing tests across 21 test files - Unit tests for all route handlers - Integration tests for API endpoints - Real integration tests for recipe scraper (live URL testing) - Authentication and authorization tests - Backup and restore functionality tests ## Configuration ### Storage Options **Local Storage (Default):** ```env STORAGE_TYPE=local LOCAL_STORAGE_PATH=./uploads ``` **S3 Storage:** ```env STORAGE_TYPE=s3 S3_BUCKET=your-bucket-name S3_REGION=us-east-1 S3_ACCESS_KEY_ID=your-access-key S3_SECRET_ACCESS_KEY=your-secret-key ``` ### Database Default PostgreSQL connection: ```env DATABASE_URL=postgresql://basil:basil@localhost:5432/basil?schema=public ``` For external database services (AWS RDS, DigitalOcean, etc.), update the connection string. ## Development ### Commands ```bash # Install dependencies npm install # Start all services in development mode npm run dev # Build all packages npm run build # Lint all packages npm run lint # Docker commands npm run docker:up npm run docker:down npm run docker:build ``` ### Database Migrations ```bash cd packages/api # Create a new migration npm run prisma:migrate # Generate Prisma client npm run prisma:generate # Open Prisma Studio (GUI for database) npm run prisma:studio ``` ## Future Enhancements - [ ] Mobile apps (React Native for iOS and Android) - [ ] Recipe sharing and social features - [ ] Meal planning and grocery lists - [ ] Nutritional information calculation - [ ] Print-friendly recipe view with custom formatting - [ ] Recipe ratings and reviews - [ ] Shopping list generation from recipes - [ ] Ingredient substitution suggestions - [ ] Recipe notes and personal modifications - [ ] Advanced search with multiple filters - [ ] Recipe version history ## License MIT ## Contributing Contributions are welcome! Please feel free to submit a Pull Request. When contributing: 1. Write tests for new features (maintain 80%+ coverage) 2. Follow existing code style and conventions 3. Update documentation as needed 4. Ensure all tests pass before submitting PR