6.3 KiB
6.3 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
# 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
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
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
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 images
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
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