## Summary - Add complete CI/CD pipeline with Gitea Actions for automated testing, building, and deployment - Implement backup and restore system with full database and file backup to ZIP - Add deployment automation with webhook receiver and systemd service - Enhance recipe editing UI with improved ingredient parsing and cooking mode features - Add comprehensive documentation for CI/CD, deployment, and backup features ## CI/CD Pipeline - New workflow in .gitea/workflows/ci-cd.yml with test, build, and deploy stages - Automated Docker image building and pushing to registry - Webhook-triggered deployments to production servers ## Backup & Restore - New backup service with ZIP creation including database dump and uploads - REST API endpoints for create, list, download, restore, and delete operations - Configurable backup path via BACKUP_PATH environment variable ## Deployment - Automated deployment scripts (deploy.sh, manual-deploy.sh) - Webhook receiver with systemd service for deployment triggers - Environment configuration template (.env.deploy.example) ## Documentation - docs/CI-CD-SETUP.md - Complete CI/CD pipeline setup guide - docs/DEPLOYMENT-QUICK-START.md - Quick deployment reference - docs/BACKUP.md - Backup and restore documentation - docs/REMOTE_DATABASE.md - Remote database configuration guide - scripts/README.md - Deployment scripts documentation ## Web Improvements - Enhanced ingredient parser with better unit and quantity detection - Improved recipe editing interface with unified edit experience - Better cooking mode functionality - Updated dependencies in package.json 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
9.2 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Basil is a full-stack recipe manager built with TypeScript. It features a REST API backend, React web frontend, and PostgreSQL database. The application supports importing recipes from URLs via schema.org markup parsing, local/S3 image storage, and comprehensive recipe management (CRUD operations, search, tagging).
Architecture
Monorepo Structure:
packages/shared/- Shared TypeScript types and interfaces used across all packagespackages/api/- Express.js REST API server with Prisma ORMpackages/web/- React + Vite web application- Future:
packages/mobile/- React Native mobile apps
Key Technologies:
- Backend: Node.js, TypeScript, Express, Prisma ORM, PostgreSQL
- Frontend: React, TypeScript, Vite, React Router
- Infrastructure: Docker, Docker Compose, nginx
- Recipe Scraping: Cheerio for HTML parsing, Schema.org Recipe markup support
Database Schema:
Recipe- Main recipe entity with metadata (prep/cook time, servings, ratings)Ingredient- Recipe ingredients with amounts, units, and orderingInstruction- Step-by-step instructions with optional imagesRecipeImage- Multiple images per recipeTag/RecipeTag- Many-to-many tagging system
Storage Architecture:
- Primary: Local filesystem storage (
./uploads) - Optional: S3 storage (configurable via environment variables)
- Storage service implements strategy pattern for easy switching
Development Commands
# Install all dependencies (root + all packages)
npm install
# Development mode (starts all packages with hot reload)
npm run dev
# Build all packages
npm run build
# Lint all packages
npm run lint
# Testing
npm test # Run all unit tests
npm run test:e2e # Run E2E tests with Playwright
npm run test:e2e:ui # Run E2E tests with Playwright UI
# Docker commands
npm run docker:up # Start all services (PostgreSQL, API, web)
npm run docker:down # Stop all services
npm run docker:build # Rebuild Docker images
Backend-Specific Commands
cd packages/api
# Development with auto-reload
npm run dev
# Database migrations
npm run prisma:migrate # Create and apply migration
npm run prisma:generate # Generate Prisma client
npm run prisma:studio # Open Prisma Studio GUI
# Build for production
npm run build
npm start
Frontend-Specific Commands
cd packages/web
# Development server
npm run dev
# Production build
npm run build
npm run preview # Preview production build locally
Configuration
Environment Variables (packages/api/.env):
PORT=3001
NODE_ENV=development
DATABASE_URL=postgresql://basil:basil@localhost:5432/basil?schema=public
STORAGE_TYPE=local # or 's3'
LOCAL_STORAGE_PATH=./uploads
BACKUP_PATH=./backups
CORS_ORIGIN=http://localhost:5173
For S3 storage, add:
S3_BUCKET=basil-recipes
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=your-key
S3_SECRET_ACCESS_KEY=your-secret
For remote PostgreSQL database, update:
DATABASE_URL=postgresql://username:password@remote-host:5432/basil?schema=public
Key Features
Recipe Import from URL
POST /api/recipes/import- Scrapes recipe from URL using schema.org markup- Extracts: title, description, ingredients, instructions, times, images
- Handles JSON-LD structured data (primary) with fallback to manual parsing
- Downloads and stores images locally or on S3
Recipe Management
- Full CRUD operations on recipes
- Pagination and search (by title, description)
- Filtering by cuisine, category
- Image upload with multiple images per recipe
- Tagging system for organization
Storage Service
- Abstracted storage interface in
packages/api/src/services/storage.service.ts - Local storage: Saves to filesystem with timestamped filenames
- S3 storage: Placeholder for AWS SDK implementation
- Easy to extend for other storage providers
Backup & Restore
- Complete data backup to single ZIP file including database and uploaded files
- Backup service in
packages/api/src/services/backup.service.ts - REST API for creating, listing, downloading, and restoring backups
- Automatic backup of all recipes, cookbooks, tags, and relationships
- Configurable backup storage location via
BACKUP_PATHenvironment variable
Adding New Features
Adding a New API Endpoint
- Add route handler in
packages/api/src/routes/*.routes.ts - Update shared types in
packages/shared/src/types.tsif needed - Rebuild shared package:
cd packages/shared && npm run build - Use Prisma client for database operations
Adding a New Frontend Page
- Create component in
packages/web/src/pages/ - Add route in
packages/web/src/App.tsx - Create API service methods in
packages/web/src/services/api.ts - Import and use shared types from
@basil/shared
Database Schema Changes
- Edit
packages/api/prisma/schema.prisma - Run
npm run prisma:migrateto create migration - Run
npm run prisma:generateto update Prisma client - Update TypeScript types in
packages/shared/src/types.tsto match
Docker Deployment
The project includes full Docker support for production deployment:
docker-compose up -d
This starts:
- PostgreSQL database (port 5432)
- API server (port 3001)
- Web frontend served via nginx (port 5173)
Persistent volumes:
postgres_data- Database storageuploads_data- Uploaded imagesbackups_data- Backup files
Using a Remote Database
To use a remote PostgreSQL database instead of the local Docker container:
- Set the
DATABASE_URLenvironment variable to point to your remote database - Update
docker-compose.ymlto pass the environment variable or create a.envfile in the root - Optionally, remove or comment out the
postgresservice and its dependency indocker-compose.yml
Example .env file in project root:
DATABASE_URL=postgresql://username:password@remote-host:5432/basil?schema=public
The docker-compose.yml is configured to use ${DATABASE_URL:-default} which will use the environment variable if set, or fall back to the local postgres container.
API Reference
Recipes:
GET /api/recipes- List all recipes (supports pagination, search, filters)GET /api/recipes/:id- Get single recipe with all relationsPOST /api/recipes- Create new recipePUT /api/recipes/:id- Update recipeDELETE /api/recipes/:id- Delete recipe and associated imagesPOST /api/recipes/:id/images- Upload image for recipePOST /api/recipes/import- Import recipe from URL
Query Parameters:
page,limit- Paginationsearch- Search in title/descriptioncuisine,category- Filter by cuisine or category
Backups:
POST /api/backup- Create a new backup (returns backup metadata)GET /api/backup- List all available backupsGET /api/backup/:filename- Download a specific backup filePOST /api/backup/restore- Restore from backup (accepts file upload or existing filename)DELETE /api/backup/:filename- Delete a backup file
Important Implementation Details
Prisma Relations
- All related entities (ingredients, instructions, images, tags) use cascade delete
- Ingredients and instructions maintain ordering via
orderandstepfields - Tags use many-to-many relationship via
RecipeTagjoin table
Recipe Scraping
- Primary: Parses JSON-LD
application/ld+jsonscripts for Schema.org Recipe data - Fallback: Extracts basic info from HTML meta tags and headings
- Handles ISO 8601 duration format (PT30M, PT1H30M) for cook times
- Downloads images asynchronously and stores them locally
Frontend Routing
- Uses React Router v6 for client-side routing
- Vite proxy forwards
/apiand/uploadsrequests to backend during development - Production uses nginx reverse proxy to backend API
TypeScript Workspace
- Root
package.jsondefines npm workspaces - Packages can reference each other (e.g.,
@basil/shared) - Must rebuild shared package when types change for other packages to see updates
CI/CD and Deployment
Basil includes a complete CI/CD pipeline with Gitea Actions for automated testing, building, and deployment.
Quick Start:
- See CI/CD Setup Guide for full documentation
- See Deployment Quick Start for quick reference
Pipeline Overview:
- Test Stage: Runs unit tests (Vitest) and E2E tests (Playwright)
- Build Stage: Builds Docker images for API and Web (main branch only)
- Deploy Stage: Pushes images to registry and triggers webhook deployment
Deployment Options:
- Automatic: Push to main branch triggers full CI/CD pipeline
- Manual: Run
./scripts/manual-deploy.shfor interactive deployment - Webhook: Systemd service listens for deployment triggers
Key Files:
.gitea/workflows/ci-cd.yml- Main CI/CD workflowscripts/deploy.sh- Deployment scriptscripts/webhook-receiver.sh- Webhook server.env.deploy.example- Deployment configuration template
Required Secrets (Gitea):
DOCKER_USERNAME- Docker Hub usernameDOCKER_PASSWORD- Docker Hub access tokenDEPLOY_WEBHOOK_URL- Webhook endpoint for deployments